📄 simulator.cpp
字号:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <windows.h>
#include <conio.h>
#include <cstring>
#pragma comment(lib, "ws2_32.lib")
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;
const int BUFFER_SIZE_CLIENT = 1024;
int console_mode = -1;
int int_mode = 0;
const int const_int_step = 1024;
SOCKET server, client1, client2;
//*****************************************************************************
//寄存器堆
struct RegHeap
{
regis T:1;
regis regh[8];
regis PC;
regis RA;
regis SP;
regis HI;
regis LO;
regis IH;
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;
//*****************************************************************************
//用于生成Intel HEX File Formt形式文件的结构
struct Hex_16
{
char colon;
char datalen[2];
char addr[4];
char type[2];
char data[4];
char checksum[2];
char newline;
Hex_16();
void create(word address, word bin_data);
};
Hex_16::Hex_16()
{
colon = ':';
datalen[0]='0';
datalen[1]='2';
newline='\n';
};
void Hex_16::create(word addr_, word data_)
{
word address = addr_;
word bin_data = data_;
for(int i=0;i<4;i++)
{
if((address & 0xF)>=0 && (address & 0xF)<=9)
addr[3-i] = char((address & 0xF)+48);
else
addr[3-i] = char((address & 0xf)+87);
address >>= 4;
}
type[0]='0';
type[1]='0';
for(int i=0;i<4;i++)
{
if((bin_data & 0xF)>=0 && (bin_data & 0xF)<=9)
data[3-i] = char((bin_data & 0xF)+48);
else
data[3-i] = char((bin_data & 0xf)+87);
bin_data >>= 4;
}
char sum = (2+(addr_>>8&0xFF)+(addr_&0xFF)+(data_>>8&0xFF)+(data_&0xFF)) % 256;
char check = ~sum + 1;
for(int i=0;i<2;i++)
{
if((check & 0xF)>=0 && (check & 0xF)<=9)
checksum[1-i] = char((check & 0xF)+48);
else
checksum[1-i] = char((check & 0xf)+87);
check >>= 4;
}
}
//内存
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 save_memFormat(char *rom_file, int pc);
void write_mem(word ,word );
word memory[MEM_SIZE];
word Mrecv[2], Msend[2];
};
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);
fclose(rom_handle);
}
void Memory::save_memFormat(char *rom_file, int pc)
{
char* endfile = ":00000001ff";
int size = pc;
word* mem16;
mem16 = new word[size];
memset(mem16, 0, size*sizeof(word));
memcpy(mem16,memory,size*sizeof(word));
Hex_16* hex16;
hex16 = new Hex_16[size];
for(int i=0; i<size; i++)
{
hex16[i].create(i,mem16[i]);
}
FILE *rom_handle = fopen(rom_file,"wb+");
fwrite(hex16,16,size,rom_handle);
fwrite(endfile,10,1,rom_handle);
fclose(rom_handle);
}
word Memory::can_vst(word index)
{
if (index < 0x2800 || (index >= 0x4000 && index < 0x6004))
return 0;
else return E_MMNVST;
}
word Memory::read_mem(word index)
{
if (index != 0x6000 && index != 0x6002)
return memory[index];
if (console_mode == 0)
{
char ch = getch();
printf("%c",ch);
memory[index] = (word)ch;
return memory[index];
}
memory[index+1] &= 0xFFFD;
return (Mrecv[(index-0x6000) >> 1] & 0xFF);
}
void Memory::write_mem(word index,word str)
{
memory[index] = str;
if (index == 0x6000 || index == 0x6002)
{
if (console_mode == 0)
printf("%c",str);
else
{
memory[index+1] &= 0xFFFE;
Msend[(index-0x6000) >> 1] = (str & 0xFF);
}
}
}
struct Memory mem;
//*****************************************************************************
//定义全部汇编指令
word index1, index2 ,index3, offset, index_jr, index_b, F , t; //index_jr临时交给jr指令使用
word IR = 0;
word PC = reg.PC;
func asm_set[32];
void run_regs(int ,char *[]);
//int
word asm_func_int(word int_num)
{
if ((reg.IH & 0x8000) == 0)
return 0;
printf("%x interrupted.\n", int_num);
reg.SP --;
if ((t = mem.can_vst(reg.SP)) != 0)
return t;
mem.memory[reg.SP] = reg.PC;
reg.SP --;
if ((t = mem.can_vst(reg.SP)) != 0)
return t;
mem.memory[reg.SP] = int_num;
reg.PC = (reg.IH & 0x7FFF);
return 0;
}
//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;
}
//NOP
word asm_01(word code)
{
return 0;
}
//B
word asm_02(word code)
{
PC = reg.PC;
if ((t = mem.can_vst(PC)) != 0) return t;
IR = mem.read_mem(PC);
index_b = ((IR >> 11) & 0x001F);
if (asm_set[index_b] == NULL)
return E_UNKNOW;
offset = (code & 0x7FF);
if ((offset & 0x400) != 0)
offset |= 0xF800;
reg.PC += offset;
asm_set[index_b](IR);
return 0;
}
//BEQZ
word asm_04(word code)
{
PC = reg.PC;
if ((t = mem.can_vst(PC)) != 0) return t;
IR = mem.read_mem(PC);
index_b = ((IR >> 11) & 0x001F);
if (asm_set[index_b] == NULL)
return E_UNKNOW;
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
if ((offset & 0x80) != 0)
offset |= 0xFF00;
if (reg.regh[index1] == 0)
{
reg.PC += offset;
asm_set[index_b](IR);
}
return 0;
}
//BNEZ
word asm_05(word code)
{
PC = reg.PC;
if ((t = mem.can_vst(PC)) != 0) return t;
IR = mem.read_mem(PC);
index_b = ((IR >> 11) & 0x001F);
if (asm_set[index_b] == NULL)
return E_UNKNOW;
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
if ((offset & 0x80) != 0)
offset |= 0xFF00;
if (reg.regh[index1] != 0)
{
reg.PC += offset;
asm_set[index_b](IR);
}
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)
{
PC = reg.PC;
if ((t = mem.can_vst(PC)) != 0) return t;
IR = mem.read_mem(PC);
index_b = ((IR >> 11) & 0x001F);
if (asm_set[index_b] == NULL)
return E_UNKNOW;
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;
asm_set[index_b](IR);
}
return 0;
case 1: //BTNEZ
if (reg.T != 0)
{
if ((offset & 0x80) != 0)
offset |= 0xFF00;
reg.PC += offset;
asm_set[index_b](IR);
}
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 4: //MTSP
index1 = (offset >> 5);
reg.SP = reg.regh[index1];
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.T = ((reg.regh[index1] ^ offset) == 0) ? 0 : 1;
return 0;
}
//LW-SP
word asm_18(word code)
{
offset = (code & 0xFF);
code >>= 8;
index1 = (code & 0x7);
if ((offset & 0x80) != 0)
offset |= 0xFF00;
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);
if ((offset & 0x80) != 0)
offset |= 0xFF00;
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
PC = reg.PC;
if ((t = mem.can_vst(PC)) != 0) return t;
IR = mem.read_mem(PC);
index_jr = ((IR >> 11) & 0x001F);
if (asm_set[index_jr] == NULL)
return E_UNKNOW;
else
{
reg.PC = reg.regh[index1];
asm_set[index_jr](IR);
return 0;
}
case 2: //MFPC
reg.regh[index1] = reg.PC;
return 0;
case 1: //JR(ra)
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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -