📄 simulator.cpp
字号:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <windows.h>
#include <conio.h>
#include <cstring>
typedef unsigned short word;
typedef unsigned short regis;
typedef word (*func) (word);
typedef void (*decode) (word);
const int LimitConsoleBuffer = 4096;
const word E_NOFILE = 1;
const word W_MMEXST = 2;
const word W_MMDRTY = 3;
const word E_UNKNOW = 4;
const word E_MMREAD = 5;
const word E_MMWRTE = 6;
const word E_MMNVST = 7;
const word E_NOFUNC = 8;
const word C_SBREAK = 9;
const word E_DIVZER = 10;
const int SCRN_X = 80;
const int SCRN_Y = 100;
void stop();
//*****************************************************************************
//寄存器堆
struct RegHeap
{
regis T:1;
regis regh[8];
regis PC;
regis RA;
regis SP;
regis HI;
regis LO;
RegHeap();
void list_regs();
};
RegHeap::RegHeap()
{
T = 0;
PC = 0x0001;
SP = 0xDFFF;
}
void RegHeap::list_regs()
{
for (int i=0;i<8;i++)
{
printf(" R%d = %04x",i,regh[i]);
if ((i+1) % 4 == 0)
printf("\n");
}
printf(" PC = %04x RA = %04x SP = %04x T = %04x\n",PC,RA,SP,T);
printf(" HI = %04x LO = %04x\n",HI,LO);
}
struct RegHeap reg;
//*****************************************************************************
//内存
struct Memory
{
word flags0, flags1;
static const word MEM_SIZE = 0xE000;
Memory();
word can_vst(word index);
word load_mem(char *rom_file);
word read_mem(word );
void save_mem(char *rom_file);
void write_mem(word ,word );
word memory[MEM_SIZE];
};
Memory::Memory()
{
flags0 = 0;
flags1 = 0;
memset(memory,0,sizeof(word)*MEM_SIZE);
};
word Memory::load_mem(char *rom_file)
{
FILE *rom_handle = fopen(rom_file,"rb");
if (rom_handle == NULL)
return E_NOFILE;
fread(memory,sizeof(word),MEM_SIZE,rom_handle);
fclose(rom_handle);
return 0;
}
void Memory::save_mem(char *rom_file)
{
FILE *rom_handle = fopen(rom_file,"wb+");
fwrite(memory,sizeof(word),MEM_SIZE,rom_handle);
}
word Memory::can_vst(word index)
{
return ((index < MEM_SIZE) ? 0 : E_MMNVST);
}
word Memory::read_mem(word index)
{
if (index == 0x8000)
{
memory[index] = (word)getch();
}
return memory[index];
}
void Memory::write_mem(word index,word str)
{
memory[index] = str;
if (index == 0x8000)
{
// printf("(%d)", str);
printf("%c",str);
}
}
struct Memory mem;
//*****************************************************************************
//定义全部汇编指令
word index1, index2 ,index3, offset, F , t;
//ADDIU_SP_3OP
word asm_00(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
if ((offset & 0x80) != 0)
offset |= 0xFF00;
reg.regh[index1] = reg.SP+offset;
return 0;
}
//B
word asm_02(word code)
{
offset = (code & 0x7FF);
if ((offset & 0x400) != 0)
offset |= 0xF800;
reg.PC += offset;
return 0;
}
//BEQZ
word asm_04(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
if ((offset & 0x80) != 0)
offset |= 0xFF00;
if (reg.regh[index1] == 0)
reg.PC += offset;
return 0;
}
//BNEZ
word asm_05(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
if ((offset & 0x80) != 0)
offset |= 0xFF00;
if (reg.regh[index1] != 0)
reg.PC += offset;
return 0;
}
//SLL SRL SRA
word asm_06(word code)
{
index3 = (code & 0x3);
code >>= 2;
offset = (code & 0x7);
code >>= 3;
index2 = (code & 0x7);
code >>= 3;
index1 = (code & 0x7);
switch (index3)
{
case 0: //SLL
reg.regh[index1] = (offset == 0) ? (reg.regh[index2] << 8) : (reg.regh[index2] << offset);
return 0;
case 2: //SRL
reg.regh[index1] = (offset == 0) ? (reg.regh[index2] >> 8) : (reg.regh[index2] >> offset);
return 0;
case 3: //SRA
reg.regh[index1] = (offset == 0) ? (((short )reg.regh[index2]) >> 8) : (((short )reg.regh[index2]) >> offset);
return 0;
default: return E_UNKNOW;
}
}
//ADDIU_3OP
word asm_08(word code)
{
offset = (code & 0xF);
code >>= 4;
index3 = (code & 0x1);
code >>= 1;
if (index3 != 0)
return E_UNKNOW;
index2 = (code & 0x7);
code >>= 3;
index1 = (code & 0x7);
if ((offset & 0x8) != 0)
offset |= 0xFFF0;
reg.regh[index2] = reg.regh[index1]+offset;
return 0;
}
//ADDIU
word asm_09(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
if ((offset & 0x80) != 0 )
offset |= 0xFF00;
reg.regh[index1] += offset;
return 0;
}
//SLTI
word asm_10(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
if ((offset & 0x80) != 0)
offset |= 0xFF00;
reg.T = ((short)reg.regh[index1] < (short)offset) ? 1 : 0;
return 0;
}
//SLTUI
word asm_11(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
reg.T = (reg.regh[index1] < offset) ? 1 : 0;
return 0;
}
//BTEQZ BTNEZ SW-RA-SP ADDIU_SP MOVE
word asm_12(word code)
{
offset = (code & 0xFF);
code >>= 8;
index3 = (code & 0x7);
switch (index3)
{
case 0: //BTEQZ
if (reg.T == 0)
{
if ((offset & 0x80) != 0)
offset |= 0xFF00;
reg.PC += offset;
}
return 0;
case 1: //BTNEZ
if (reg.T != 0)
{
if ((offset & 0x80) != 0)
offset |= 0xFF00;
reg.PC += offset;
}
return 0;
case 2: //SW-RA-SP
F = reg.SP+offset;
if ((t = mem.can_vst(F)) != 0) return t;
mem.write_mem(F,reg.RA);
return 0;
case 3: // ADDIU_SP
if ((offset & 0x80) != 0)
offset |= 0xFF00;
reg.SP += offset;
return 0;
case 7: //MOVE
index2 = (offset & 0x7);
offset >>= 3;
if ((offset & 0x3) != 0)
return E_UNKNOW;
offset >>= 2;
index1 = (offset & 0x7);
reg.regh[index1] = reg.regh[index2];
return 0;
default: return E_UNKNOW;
}
}
//LI
word asm_13(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
reg.regh[index1] = offset;
return 0;
}
//CMPI
word asm_14(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
reg.regh[index1] ^= offset;
return 0;
}
//LW-SP
word asm_18(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
F = reg.SP+offset;
if ((t = mem.can_vst(F)) != 0) return t;
reg.regh[index1] = mem.read_mem(F);
return 0;
}
//LW
word asm_19(word code)
{
offset = (code & 0x1F);
code >>= 5;
index2 = (code & 0x7);
code >>= 3;
index1 = (code & 0x7);
F = reg.regh[index1]+offset;
if ((t = mem.can_vst(F)) != 0) return t;
reg.regh[index2] = mem.read_mem(F);
return 0;
}
//SW-SP
word asm_26(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
F = reg.SP+offset;
if ((t = mem.can_vst(F)) != 0) return t;
mem.write_mem(F,reg.regh[index1]);
return 0;
}
//SW
word asm_27(word code)
{
offset = (code & 0x1F);
code >>= 5;
index2 = (code & 0x7);
code >>= 3;
index1 = (code & 0x7);
F = reg.regh[index1]+offset;
if ((t = mem.can_vst(F)) != 0) return t;
mem.write_mem(F,reg.regh[index2]);
return 0;
}
//ADDU SUBU
word asm_28(word code)
{
offset = (code & 0x3);
code >>= 2;
index3 = (code & 0x7);
code >>= 3;
index2 = (code & 0x7);
code >>= 3;
index1 = (code & 0x7);
switch (offset)
{
case 1: //ADDU
reg.regh[index3] = reg.regh[index1]+reg.regh[index2];
return 0;
case 3: //SUBU
reg.regh[index3] = reg.regh[index1]-reg.regh[index2];
return 0;
default: return E_UNKNOW;
}
}
//JR(ra) JR MFHI MFLO JALR SLT SLTU SLLV SRLV SRAV CMP NEG AND OR XOR NOT MULT MULTU DIV DIVU
word asm_29(word code)
{
index3 = (code & 0x1F);
code >>= 5;
index2 = (code & 0x7);
code >>= 3;
index1 = (code & 0x7);
if (index3 == 0)
{
switch (index2)
{
case 0: //JR(ra)
reg.PC = reg.regh[index1];
return 0;
case 2: //MFPC
reg.regh[index1] = reg.PC;
return 0;
case 1: //JR
if (index1 != 0) return E_UNKNOW;
reg.PC = reg.RA;
return 0;
case 6: //JALR
reg.RA = reg.PC;
reg.PC = reg.regh[index1];
return 0;
default: return E_UNKNOW;
}
}
unsigned int mul;
switch (index3)
{
case 2: //SLT
reg.T = ((short)reg.regh[index1] < (short)reg.regh[index2]) ? 1 : 0;
return 0;
case 3: //SLTU
reg.T = (reg.regh[index1] < reg.regh[index2]) ? 1 : 0;
return 0;
case 4: //SLLV
reg.regh[index2] = (reg.regh[index2] << reg.regh[index1]);
return 0;
case 6: //SRLV
reg.regh[index2] = (reg.regh[index2] >> reg.regh[index1]);
return 0;
case 7: //SRAV
reg.regh[index2] = (((short )reg.regh[index2]) >> reg.regh[index1]);
return 0;
case 10: //CMP
reg.regh[index1] ^= reg.regh[index2];
return 0;
case 11: //NEG
reg.regh[index1] = -reg.regh[index2];
return 0;
case 12: //AND
reg.regh[index1] &= reg.regh[index2];
return 0;
case 13: //OR
reg.regh[index1] |= reg.regh[index2];
return 0;
case 14: //XOR
reg.regh[index1] ^= reg.regh[index2];
return 0;
case 15: //NOT
reg.regh[index1] = ~reg.regh[index2];
return 0;
case 16: //MFHI
reg.regh[index1] = reg.HI;
return 0;
case 18: //MFLO
reg.regh[index1] = reg.LO;
return 0;
case 24: //MULT
mul = (int)reg.regh[index1]*(int)reg.regh[index2];
reg.HI = (word)((mul >> 16) & 0xFFFF);
reg.LO = (word)(mul & 0xFFFF);
return 0;
case 25: //MULTU
mul = (unsigned int)(reg.regh[index1])*(unsigned int)(reg.regh[index2]);
reg.HI = (word)((mul >> 16) & 0xFFFF);
reg.LO = (word)(mul & 0xFFFF);
return 0;
case 26: //DIV
if (reg.regh[index2] == 0)
return E_DIVZER;
reg.LO = (word)((short)reg.regh[index1]/(short)reg.regh[index2]);
reg.HI = (word)((short)reg.regh[index1]%(short)reg.regh[index2]);
return 0;
case 27: //DIVU
if (reg.regh[index2] == 0)
return E_DIVZER;
reg.LO = reg.regh[index1]/reg.regh[index2];
reg.HI = reg.regh[index1]%reg.regh[index2];
return 0;
default: return E_UNKNOW;
}
}
//*****************************************************************************
//解码
void unknown_printf()
{
printf("**********");
}
void unknown_decode(word code)
{
printf("---unknown--- <%04x>",code);
}
//ADDIU_SP_3OP
void decode_00(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
if ((offset & 0x80) != 0)
offset |= 0xFF00;
printf("ADDSP R%x %04x",index1,offset);
}
//B
void decode_02(word code)
{
offset = (code & 0x7FF);
if ((offset & 0x400) != 0)
offset |= 0xF800;
printf("B %04x",offset);
}
//BEQZ
void decode_04(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
if ((offset & 0x80) != 0)
offset |= 0xFF00;
printf("BEQZ R%x %04x",index1,offset);
}
//BNEZ
void decode_05(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
if ((offset & 0x80) != 0)
offset |= 0xFF00;
printf("BNEZ R%x %04x",index1,offset);
}
//SLL SRL SRA
void decode_06(word code)
{
index3 = (code & 0x3);
code >>= 2;
offset = (code & 0x7);
code >>= 3;
index2 = (code & 0x7);
code >>= 3;
index1 = (code & 0x7);
switch (index3)
{
case 0: printf("SLL "); break;
case 2: printf("SRL "); break;
case 3: printf("SRA "); break;
default:
unknown_printf();
return ;
}
printf(" R%x R%x %04x",index1,index2,offset);
}
//ADDIU_3OP
void decode_08(word code)
{
offset = (code & 0xF);
code >>= 4;
index3 = (code & 0x1);
code >>= 1;
if (index3 != 0)
{
unknown_printf();
return ;
}
index2 = (code & 0x7);
code >>= 3;
index1 = (code & 0x7);
if ((offset & 0x8) != 0)
offset |= 0xFFF0;
printf("ADDIU R%x R%x %04x",index1,index2,offset);
}
//ADDIU
void decode_09(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
if ((offset & 0x80) != 0 )
offset |= 0xFF00;
printf("ADDIU R%x %04x",index1,offset);
}
//SLTI
void decode_10(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
if ((offset & 0x80) != 0)
offset |= 0xFF00;
printf("SLTI R%x %04x",index1,offset);
}
//SLTUI
void decode_11(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
printf("SLTUI R%x %04x",index1,offset);
}
//BTEQZ BTNEZ SW-RA-SP ADDIU_SP MOVE
void decode_12(word code)
{
offset = (code & 0xFF);
code >>= 8;
index3 = (code & 0x7);
switch (index3)
{
case 0: //BTEQZ
if ((offset & 0x80) != 0)
offset |= 0xFF00;
printf("BTEQZ");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -