📄 cpu.cpp
字号:
//class CPU implementing
//refer to CPU.h , Relationships between CPU and Instruction
#include "stdafx.h"
#include "DFYSimulator.h"
#include "CPU.H"
#include "MainFrm.h"
#include "OutputWindow.h"
#include "iostream"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#include "IRQDlg.h"
#include "Instruction.h"
#include "BUSSystem.h"
//default construction
CPU::CPU()
{
//General register
for(int i=0;i<5;i++)
GR[i]=0;
//Segment register
CS=0;
DS=0;
ES=0;
SS=0;
//Offset register
IP=0;
SP=0;
PC=0;
//Flags register
FLAGS=0;
//Current instruction
OP=0;//code
_instruction=NULL;
_busSystem=NULL;
m_bBG=FALSE;
m_bContinue=TRUE;
m_bIRQ=FALSE;
m_bIRQMask=0;
_IRQDlg=NULL;
for(int j=0;j<MAXNUMBER;j++)
_instructionEntry[j]=NULL;
}
//destruction
CPU::~CPU()
{
Instruction *pInstruction;
for(int j=0;j<MAXNUMBER;j++)
{
pInstruction=_instructionEntry[j];
if(pInstruction)delete pInstruction;
}
}
//Initalize
void CPU::Initialize()
{
//initialize instruction
LD* pLD=new LD();
if(!pLD)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
ST* pST=new ST();
if(!pST)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
LEA* pLEA =new LEA();
if(!pLEA)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
ADD* pADD=new ADD();
if(!pADD)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
SUB* pSUB=new SUB();
if(!pSUB)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
SLA* pSLA=new SLA();
if(!pSLA)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
SRA* pSRA=new SRA();
if(!pSRA)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
AND* pAND=new AND();
if(!pAND)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
OR* pOR=new OR();
if(!pOR)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
EOR* pEOR=new EOR();
if(!pEOR)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
NOT* pNOT=new NOT();
if(!pNOT)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
SLL* pSLL=new SLL();
if(!pSLL)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
SRL* pSRL=new SRL();
if(!pSRL)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
CPA* pCPA=new CPA();
if(!pCPA)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
CPL* pCPL=new CPL();
if(!pCPL)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
JMP* pJMP=new JMP();
if(!pJMP)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
JPZ* pJPZ=new JPZ();
if(!pJPZ)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
JMI* pJMI=new JMI();
if(!pJMI)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
JNZ* pJNZ=new JNZ();
if(!pJNZ)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
JZE* pJZE=new JZE();
if(!pJZE)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
PUSH* pPUSH=new PUSH();
if(!pPUSH)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
POP* pPOP=new POP();
if(!pPOP)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
CALL* pCALL=new CALL();
if(!pCALL)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
RET* pRET=new RET();
if(!pRET)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
INPORT* pINPORT=new INPORT();
if(!pINPORT)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
OUTPORT* pOUTPORT=new OUTPORT();
if(!pOUTPORT)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
EXIT* pEXIT=new EXIT();
if(!pEXIT)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
CLI* pCLI=new CLI();
if(!pCLI)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
STI* pSTI=new STI();
if(!pSTI)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
IRET* pIRET=new IRET();
if(!pIRET)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
INTR* pINTR=new INTR();
if(!pINTR)
{
MessageBox(NULL,"not enough memory !","Fatal error !",MB_OK);
return;
}
//load instruction
AddInstruction(pLD,pLD->GetinstructionCode());
AddInstruction(pST,pST->GetinstructionCode());
AddInstruction(pLEA,pLEA->GetinstructionCode());
AddInstruction(pADD,pADD->GetinstructionCode());
AddInstruction(pSUB,pSUB->GetinstructionCode());
AddInstruction(pSLA,pSLA->GetinstructionCode());
AddInstruction(pSRA,pSRA->GetinstructionCode());
AddInstruction(pAND,pAND->GetinstructionCode());
AddInstruction(pOR,pOR->GetinstructionCode());
AddInstruction(pEOR,pEOR->GetinstructionCode());
AddInstruction(pNOT,pNOT->GetinstructionCode());
AddInstruction(pSLL,pSLL->GetinstructionCode());
AddInstruction(pSRL,pSRL->GetinstructionCode());
AddInstruction(pCPA,pCPA->GetinstructionCode());
AddInstruction(pCPL,pCPL->GetinstructionCode());
AddInstruction(pJMP,pJMP->GetinstructionCode());
AddInstruction(pJPZ,pJPZ->GetinstructionCode());
AddInstruction(pJMI,pJMI->GetinstructionCode());
AddInstruction(pJNZ,pJNZ->GetinstructionCode());
AddInstruction(pJZE,pJZE->GetinstructionCode());
AddInstruction(pPUSH,pPUSH->GetinstructionCode());
AddInstruction(pPOP,pPOP->GetinstructionCode());
AddInstruction(pCALL,pCALL->GetinstructionCode());
AddInstruction(pRET,pRET->GetinstructionCode());
AddInstruction(pINPORT,pINPORT->GetinstructionCode());
AddInstruction(pOUTPORT,pOUTPORT->GetinstructionCode());
AddInstruction(pEXIT,pEXIT->GetinstructionCode());
AddInstruction(pCLI,pCLI->GetinstructionCode());
AddInstruction(pSTI,pSTI->GetinstructionCode());
AddInstruction(pIRET,pIRET->GetinstructionCode());
AddInstruction(pINTR,pINTR->GetinstructionCode());
}
//attribute
void CPU::SetGR(WORD wGR,BYTE bIndex)
{
if(bIndex<0||bIndex>4)
{
ReportState("Sorry,the register you want acess is not exist");
return;
}
GR[bIndex]=wGR;
}
WORD CPU::GetGR(BYTE bIndex)
{
if(bIndex<0||bIndex>4)
{
ReportState("Sorry,the register you want acess is not exist");
return 0;
}
return GR[bIndex];
}
//specify Instruction for each Instruction code
int CPU::AddInstruction(Instruction* lpInstruction,BYTE bCode)
{
if(bCode<0)
{
ReportState("sorry ,the Instruction code\ncan't below 0 ");
return 0;
}
_instructionEntry[bCode]=lpInstruction;
lpInstruction->SetCPU(this);
return bCode;
}
Instruction* CPU::GetInstruction(BYTE bIndex)
{
if(bIndex<0||bIndex>127)
{
ReportState("Sorry,the instruction you\n want is not exist,the value of bIndex is illegal");
return NULL;
}
else
return _instructionEntry[bIndex];
}
//BUS operation
UNSHORT CPU::ReadAddrFromAddrBUS()
{
if(!m_bBG)//if the CPU not occupying the BUS
{
ReportState("Sorry! You can't use this operation,because you haven't get the BUS control. Please call the function RequstBUS() first");
return 0;
}
UNSHORT uAddr;
if(_busSystem)
{
_busSystem->ReadAddrFromAddrBUS(uAddr);
return uAddr;
}
else
{
ReportState("Sorry! CPU can't find BUSSystem,Attach it to a BUSSystem and try again");
return 0;
}
}
void CPU::WriteAddrToAddrBUS(UNSHORT uAddr)
{
if(!m_bBG)//if the CPU not occupying the BUS
{
ReportState("Sorry! You can't use this operation,because you haven't get the BUS control. Please call the function RequstBUS() first");
return;
}
if(_busSystem)
{
_busSystem->WriteAddrToAddrBUS(uAddr);
return;
}
else
{
ReportState("Sorry , CPU can't find BUSSystem,Attach it to a BUSSystem and try again");
return;
}
}
void CPU::SetIORead(BOOL bState)
{
if(!m_bBG)//if the CPU not occupying the BUS
{
ReportState("Sorry! You can't use this operation,because you haven't get the \n\
BUS control. Please call the \n\
function RequstBUS() first");
return;
}
if(_busSystem)
{
_busSystem->SetIORead(bState);
return;
}
else
{
ReportState("Sorry , CPU can't find BUSSystem,\n\
Attach it to a BUSSystem and \n\
try again");
return ;
}
}
void CPU::SetIOWrite(BOOL bState)
{
if(!m_bBG)//if the CPU not occupying the BUS
{
ReportState("Sorry! You can't use this operation,\n\
because you haven't get the \n\
BUS control. Please call the \n\
function RequstBUS() first");
return;
}
if(_busSystem)
{
_busSystem->SetIOWrite(bState);
return;
}
else
{
ReportState("Sorry , CPU can't find BUSSystem,\n\
Attach it to a BUSSystem and \n\
try again");
return ;
}
}
WORD CPU::ReadDataFromMemory()
{
if(!m_bBG)//if the CPU not occupy the BUS
{
ReportState("Sorry! You can't use this operation,\n\
because you haven't get the \n\
BUS control. Please call the \n\
function RequstBUS() first");
return 0;
}
WORD wData;
if(_busSystem)
{
SetIORead(FALSE);//set the IO state to Read
_busSystem->AccessMemory();//read data from memory and
//put it into the DataBUS
_busSystem->ReadDataFromDataBUS(wData);
SetIORead(TRUE);//reset the IO Read state
return wData;
}
else
{
ReportState("Sorry , CPU can't find BUSSystem,\n\
Attach it to a BUSSystem and \n\
try again");
return 0;
}
}
void CPU::WriteDataToMemory(WORD& wData)
{
if(!m_bBG)//if the CPU not occupying the BUS
{
ReportState("Sorry! You can't use this operation,\n\
because you haven't get the \n\
BUS control. Please call the \n\
function RequstBUS() first");
return;
}
if(_busSystem)
{
SetIOWrite(FALSE);//set the Write state
_busSystem->WriteDataToDataBUS(wData);
_busSystem->AccessMemory();
SetIOWrite(TRUE);//reset the Write state
return;
}
else
{
ReportState("Sorry , CPU can't find BUSSystem,\n\
Attach it to a BUSSystem and \n\
try again");
return;
}
}
void CPU::RequestBUS()
{
if(_busSystem)
{
while(!(m_bBG=_busSystem->Determine()));
return;
}
else
{
ReportState("Sorry , CPU can't find BUSSystem,Attach it to a BUSSystem and try again!");
return;
}
}
void CPU::ReleaseBUS()
{
if(_busSystem)
{
m_bBG=FALSE;
_busSystem->SetBS(FALSE);
}
else
{
ReportState("Sorry , CPU can't find BUSSystem,Attach it to a BUSSystem and try again");
return;
}
}
//operation
void CPU::LoadInstructionFromMemory()//load a instruction from memory
{
DWORD dwOP;//will hold the operation code
WORD wData=0;
UNSHORT uAddr=PC;
RequestBUS();
WriteAddrToAddrBUS(uAddr);
wData=ReadDataFromMemory();
ReleaseBUS();
dwOP=(DWORD)wData;
OP=dwOP<<16;
RequestBUS();
uAddr+=1;
WriteAddrToAddrBUS(uAddr);
wData=ReadDataFromMemory();
ReleaseBUS();
dwOP=DWORD(wData);
OP+=dwOP;
}
void CPU::Excute()
{
if((GetFLAGS()&0X0008))//if set the IF flag
{
if(_IRQDlg)
{
m_bIRQ=_IRQDlg->GetIRQState();
if(m_bIRQ)//if have Interrupt Request
{
Ack();//ack
_IRQDlg->Determine();
UINT uIRQNum=_IRQDlg->GetCurIRQNum();
if(uIRQNum<=8)//if the uIRQNum is legal
{
CString str1;
str1.Format("handle IRQ%d interrupt...",uIRQNum);
_IRQDlg->ReportHandleState(str1);
CString str2;
str2.Format("IRQ%d",uIRQNum);
_IRQDlg->DeleteStr(str2);
BYTE bReqBit=_IRQDlg->GetReqBit();
BYTE bMask=~(0X01<<(uIRQNum-1));
bReqBit&=bMask;
_IRQDlg->SetReqBit(bReqBit);
str1.Format("handle IRQ%d succeed",uIRQNum);
_IRQDlg->ReportHandleState(str1);
return;
}
}
}
}//end: set the TF flag
if((GetFLAGS() & 0X0010))//if set TF flag ,will cause the step interrupt
{
if(m_bContinue)
{
LoadInstructionFromMemory();
BYTE bCode1=BYTE(OP>>25);
_instruction=GetInstruction(bCode1);
_instruction->Excute(OP);//excute the Code
m_bContinue=FALSE;
}
else
{
//idle
//do nothing until the user set the m_bContinue
//state to TRUE
}
}
else
{
LoadInstructionFromMemory();
BYTE bCode2=BYTE(OP>>25);//specify the Instruction code
_instruction=GetInstruction(bCode2);
if(_instruction)
{
_instruction->Excute(OP);
}
else
{
ReportState("Sorry, no appropriate instruction handle\n this operation code");
}
}
}
//feature that will use in future
int CPU::AddRegister(LPCTSTR lpRegisterName)
{
return 0;
}
void CPU::ReportState(CString strState)
{
CMainFrame* pMainFrame=(CMainFrame*)AfxGetMainWnd();
COutputWindow* pOutputWindow=pMainFrame->GetOutputWindow();
if(pOutputWindow)
{
pOutputWindow->ShowState(strState);
}
}
void CPU::Ack()
{
if(_IRQDlg)
_IRQDlg->ReportHandleState("_cpu ACK...");
}
void CPU::SetIRQMask(BYTE bMask)
{
m_bIRQMask=bMask;
}
BYTE CPU::GetIRQMask()
{
return m_bIRQMask;
}
void CPU::SetIntCtrl(CIRQDlg *pIRQDlg)
{
_IRQDlg=pIRQDlg;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -