📄 cpu.c
字号:
if (!load_halfword(vaddr,phyaddr,cache_able,DATA_LOAD,&data))
{
//an exception has occured when load_halfword
}
else
{
/*we must convert data to signed value*/
return_value = (INT16)data;
cpu_register[get_rt(instruction)]= (INT32)return_value;
}
//}
}
/* lwl algorithms is taken from VMIPS*/
UINT32
lwl(UINT32 regval, UINT32 memval, UINT8 offset)
{
if (target_end==BIGEND) {
switch (offset)
{
case 0: return memval;
case 1: return ((memval & 0xffffff) << 8) | (regval & 0xff);
case 2: return ((memval & 0xffff) << 16) | (regval & 0xffff);
case 3: return ((memval & 0xff) << 24) | (regval & 0xffffff);
}
} else /* if MIPS target is little endian */ {
switch (offset)
{
case 0: return ((memval & 0xff)) << 24 | (regval & 0xffffff);
case 1: return ((memval & 0xffff)) << 16 | (regval & 0xffff);
case 2: return ((memval & 0xffffff)) << 8 | (regval & 0xff);
case 3: return memval;
}
}
//fprintf("""Invalid offset %x passed to lwl\n", offset);
}
UINT32
lwr(UINT32 regval, UINT32 memval, UINT8 offset)
{
if (target_end==BIGEND) {
switch (offset)
{
case 0: return (regval & 0xffffff00) |
((unsigned)(memval & 0xff000000) >> 24);
case 1: return (regval & 0xffff0000) |
((unsigned)(memval & 0xffff0000) >> 16);
case 2: return (regval & 0xff000000) |
((unsigned)(memval & 0xffffff00) >> 8);
case 3: return memval;
}
} else /* if MIPS target is little endian */ {
switch (offset)
{
/* The SPIM source claims that "The description of the
* little-endian case in Kane is totally wrong." The fact
* that I ripped off the LWR algorithm from them could be
* viewed as a sort of passive assumption that their claim
* is correct.
*/
case 0: /* 3 in book */
return memval;
case 1: /* 0 in book */
return (regval & 0xff000000) | ((memval & 0xffffff00) >> 8);
case 2: /* 1 in book */
return (regval & 0xffff0000) | ((memval & 0xffff0000) >> 16);
case 3: /* 2 in book */
return (regval & 0xffffff00) | ((memval & 0xff000000) >> 24);
}
}
//fatal_error("Invalid offset %x passed to lwr\n", offset);
}
/*opcode = 34 lwl t,0(b)*/
static void lwl_simulate(const UINT32 instruction)
{
UINT32 base_addr,vaddr,phyaddr,wordvaddr;
INT32 offset;
boolean cache_able;
UINT8 word_offset;
UINT32 memory_data;
offset = get_offset(instruction);
base_addr = cpu_register[get_rb(instruction)];
vaddr = base_addr + offset;
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,0x%x(%s)","lwl",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
/**/
wordvaddr = vaddr & 0xfffffffc;
word_offset = vaddr & 0x00000003;
if ((vaddr % 4)!=0)
{
//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
//bad address exctiption
//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
exception(ADEL,-1);
//else
// exception(ADES,-1);
return ;
}
phyaddr = vaddr2phyaddr(wordvaddr,DATA_LOAD,&cache_able);
if ((phyaddr % 4)!=0)
{
//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
//bad address exctiption
//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
exception(ADEL,-1);
//else
// exception(ADES,-1);
return ;
}
if (0xffffffff== phyaddr )
{
//an exception has occured
}
else
{
if (!load_word(vaddr,phyaddr,cache_able,DATA_LOAD,&memory_data))
{ //an exception has occured
}
else
{
cpu_register[get_rt(instruction)] = lwl(cpu_register[get_rt(instruction)], memory_data, word_offset);
}
}
}
/*opcode = 35 lw t,0(b)*/
static void lw_simulate(const UINT32 instruction)
{
UINT32 base_addr,vaddr,phyaddr;
INT32 offset;
boolean cache_able;
UINT32 data;
INT32 return_value;
offset = get_offset(instruction);
base_addr = cpu_register[get_rb(instruction)];
vaddr = base_addr + offset;
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,0x%x(%s)","lw",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
//printf("base_addr 0x%x\n",base_addr);
//printf("base_addr 0x%x\n",offset);
//printf("vaddr 0x%x\n",vaddr);
if ((vaddr % 4)!=0)
{
//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
//bad address exctiption
//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
exception(ADEL,-1);
//else
// exception(ADES,-1);
return ;
}
phyaddr = vaddr2phyaddr(vaddr,DATA_LOAD,&cache_able);
if ((phyaddr % 4)!=0)
{
//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
//bad address exctiption
//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
exception(ADEL,-1);
//else
// exception(ADES,-1);
return ;
}
//printf("phyaddr 0x%x",phyaddr);
if (0xffffffff ==phyaddr )
{
//an exception has occured when addr->phyaddr
}
else
{
if (!load_word(vaddr,phyaddr,cache_able,DATA_LOAD,&data))
{
//printf("exception \n");
//an exception has occured when load_halfword
}
else
{
/*we must convert data to signed value*/
//printf("data 0x%x\n",data);
return_value = (INT32)data;
cpu_register[get_rt(instruction)]= (INT32)return_value;
}
}
}
/*opcode = 36 lbu t,0(b)*/
static void lbu_simulate(const UINT32 instruction)
{
UINT32 base_addr,vaddr,phyaddr;
INT32 offset;
boolean cache_able;
UINT8 data;
UINT8 return_value;
offset = get_offset(instruction);
base_addr = cpu_register[get_rb(instruction)];
vaddr = base_addr + offset;
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,0x%x(%s)","lbu",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
phyaddr = vaddr2phyaddr(vaddr,DATA_LOAD,&cache_able);
if (0xffffffff== phyaddr )
{
//an exception has occured when addr->phyaddr
}
else
{
if (!load_byte(vaddr,phyaddr,cache_able,DATA_LOAD,&data))
{
//an exception has occured when load_halfword
}
else
{
/*we must convert data to signed value*/
return_value = (UINT8)data;
cpu_register[get_rt(instruction)]= (UINT32)return_value;
}
}
}
/*opcode = 37 lhu t,0(b)*/
static void lhu_simulate(const UINT32 instruction)
{
UINT32 base_addr,vaddr,phyaddr;
INT32 offset;
boolean cache_able;
UINT16 data;
UINT16 return_value;
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,0x%x(%s)","lhu",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
offset = get_offset(instruction);
base_addr = cpu_register[get_rb(instruction)];
vaddr = base_addr + offset;
if ((vaddr % 2)!=0)
{
//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
//bad address exctiption
//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
exception(ADEL,-1);
//else
// exception(ADES,-1);
return ;
}
phyaddr = vaddr2phyaddr(vaddr,DATA_LOAD,&cache_able);
if ((vaddr % 2)!=0)
{
//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
//bad address exctiption
//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
exception(ADEL,-1);
//else
// exception(ADES,-1);
return ;
}
if (0xffffffff== phyaddr )
{
//an exception has occured when addr->phyaddr
}
else
{
if (!load_halfword(vaddr,phyaddr,cache_able,DATA_LOAD,&data))
{
//an exception has occured when load_halfword
}
else
{
/*we must convert data to signed value*/
return_value = (UINT16)data;
cpu_register[get_rt(instruction)]= (UINT32)return_value;
}
}
}
/*opcode = 38 lwr t,0(b)*/
static void lwr_simulate(const UINT32 instruction)
{
UINT32 base_addr,vaddr,phyaddr,wordvaddr;
INT32 offset;
boolean cache_able;
UINT8 word_offset;
UINT32 memory_data;
offset = get_offset(instruction);
base_addr = cpu_register[get_rb(instruction)];
vaddr = base_addr + offset;
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,0x%x(%s)","lwr",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
/**/
wordvaddr = vaddr & 0xfffffffc;
word_offset = vaddr & 0x00000003;
if ((vaddr % 4)!=0)
{
//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
//bad address exctiption
//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
exception(ADEL,-1);
//else
// exception(ADES,-1);
return ;
}
phyaddr = vaddr2phyaddr(wordvaddr,DATA_LOAD,&cache_able);
if ((phyaddr % 4)!=0)
{
//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
//bad address exctiption
//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
exception(ADEL,-1);
//else
// exception(ADES,-1);
return ;
}
if (0xffffffff== phyaddr )
{
//an exception has occured
}
else
{
if (!load_word(vaddr,phyaddr,cache_able,DATA_LOAD,&memory_data))
{ //an exception has occured
}
else
{
cpu_register[get_rt(instruction)] = lwr(cpu_register[get_rt(instruction)], memory_data, word_offset);
}
}
}
/*opcode = 39 lwu t,0(b) MIPS III*/
/*opcode = 40 sb t,0(b)*/
static void sb_simulate(const UINT32 instruction)
{
UINT32 base_addr,vaddr,phyaddr;
INT32 offset;
boolean cache_able;
UINT8 data;
offset = get_offset(instruction);
base_addr = cpu_register[get_rb(instruction)];
vaddr = base_addr + offset;
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,0x%x(%s)","sb",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
data = cpu_register[get_rt(instruction)]&0x000000ff;
phyaddr = vaddr2phyaddr(vaddr,DATA_STORE,&cache_able);
if (0xffffffff== phyaddr )
{
//an exception has occured
}
else
{
store_byte(vaddr,phyaddr,cache_able,DATA_STORE,data);
}
}
/*opcode = 41 sh t,0(b)*/
static void sh_simulate(const UINT32 instruction)
{
UINT32 base_addr,vaddr,phyaddr;
INT32 offset;
boolean cache_able;
UINT16 data;
offset = get_offset(instruction);
base_addr = cpu_register[get_rb(instruction)];
vaddr = base_addr + offset;
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,0x%x(%s)","sh",reg_table[get_rt(instruction)],offset, reg_table[get_rb(instruction)]);
data = cpu_register[get_rt(instruction)]&0x0000ffff;
if ((vaddr % 2)!=0)
{
//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
//bad address exctiption
//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
// exception(ADEL,-1);
//else
exception(ADES,-1);
return ;
}
phyaddr = vaddr2phyaddr(vaddr,DATA_STORE,&cache_able);
if ((phyaddr % 2)!=0)
{
//fprintf(stderr,"vaddr % 4- !=0---------------------------------!\n");
//bad address exctiption
//if ((operation_mode==DATA_LOAD)||(operation_mode==INSTRUCTION_LOAD))
// exception(ADEL,-1);
//else
exception(ADES,-1);
return ;
}
if (0xffffffff== phyaddr )
{
//an exception has occured
}
else
{
store_halfword(vaddr,phyaddr,cache_able,DATA_STORE,data);
}
}
UINT32
swl(UINT32 regval, UINT32 memval, UINT8 offset)
{
if (host_end) {
switch (offset) {
case 0: return regval;
case 1: return (memval & 0xff000000) | (regval >> 8 & 0xffffff);
case 2: return (memval & 0xffff0000) | (regval >> 16 & 0xffff);
case 3: return (memval & 0xffffff00) | (regval >> 24 & 0xff);
}
} else /* if MIPS target is little endian */ {
switch (offset) {
case 0: return (memval & 0xffffff00) | (regval >> 24 & 0xff);
case 1: return (memval & 0xffff0000) | (regval >> 16 & 0xffff);
case 2: return (memval & 0xff000000) | (regval >> 8 & 0xffffff);
case 3: return regval;
}
}
//fatal_error("Invalid offset %x passed to swl\n", offset);
}
UINT32
swr(UINT32 regval, UINT32 memval, UINT8 offset)
{
if (host_end) {
switch (offset) {
case 0: return ((regval << 24) & 0xff000000) | (memval & 0xffffff);
case 1: return ((regval << 16) & 0xffff0000) | (memval & 0xffff);
case 2: return ((regval << 8) & 0xffffff00) | (memval & 0xff);
case 3: return regval;
}
} else /* if MIPS target is little endian */ {
switch (offset) {
case 0: return regval;
case 1: return ((regval << 8) & 0xffffff00) | (memval & 0xff);
case 2: return ((regval << 16) & 0xffff0000) | (memval & 0xffff);
case 3: return ((regval << 24) & 0xff000000) | (memval & 0xffffff);
}
}
//fatal_error("Invalid offset %x passed to swr\n", offset);
}
/*opcode = 42 swl t,0(b)*/
static void swl_simulate(const UINT32 instruction)
{
UINT32 base_addr,vaddr,phyaddr;
INT32 offset;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -