📄 cpu.c
字号:
if (load_byte_from_memory(phyaddr, data))
return true;
else
return false;
}
}
static boolean load_halfword_from_memory(UINT32 phyaddr,UINT16 * data)
{
UINT32 offset;
//UINT8 halfword_offset;
/*notice: last bit of phyaddr =0,so we must >>1*/
//halfword_offset = (phyaddr>>1) & 0x00000001;
//phyaddr = phyaddr & 0xfffffffe;
if (phyaddr<=RAM_UPPER_BOUND)
{
//RAM
offset = phyaddr - RAM_LOWER_BOUND;
*data = bytes2halfword(&ram[offset]);
}
else if ((phyaddr>=ROM_LOWER_BOUND) && ( phyaddr<=ROM_UPPER_BOUND))
{
//ROM
offset = phyaddr - ROM_LOWER_BOUND;
*data = bytes2halfword(&rom[offset]);
}
else if ((phyaddr>=CONSOLE_LOWER_ADDR)&&(phyaddr<=CONSOLE_UPPER_ADDR))
{
*data = console_load_halfword();
}
else
{
//bad address exception
exception(ADEL,-1);
return false;
}
}
static boolean load_halfword_from_cache(UINT32 vaddr,UINT32 phyaddr,int operation_mode,UINT16 * data)
{
UINT32 index,word_vaddr;
/*because we just fetch half word form cache. So we must get the offset of cache line.*/
UINT8 cache_line_offset;
/*notice: last bit of phyaddr =0,so we must >>1*/
cache_line_offset = (vaddr>>1) & 0x00000001;
/*set the last 2 bits to zero*/
word_vaddr = vaddr & 0xfffffffc;
if (true ==is_swc())
{
if (DATA_LOAD == operation_mode )
{
operation_mode = INSTRUCTION_LOAD;
}
else if (INSTRUCTION_LOAD == operation_mode )
operation_mode = DATA_LOAD;
}
if (DATA_LOAD==operation_mode)
{
index = (phyaddr & DCACHE_MASK) ;
if ( (is_isc()==true) || ( (dcache[index].tag == word_vaddr) && (dcache[index].flag & CACHE_VALID_MASK) ))
{
//hit
*data = get_halfword_from_word(dcache[index].cache_line,cache_line_offset);
return true;
}
else
{
//miss
return false;
}
}
else if (INSTRUCTION_LOAD==operation_mode)
{
index = phyaddr & ICACHE_MASK;
if ((is_isc()==true)||( (icache[index].tag == word_vaddr) && (icache[index].flag & CACHE_VALID_MASK) ))
{
//hit
*data = get_halfword_from_word(icache[index].cache_line,cache_line_offset);
return true;
}
else
{
return false;
}
}
}
static boolean load_halfword(UINT32 vaddr,UINT32 phyaddr,boolean cache_able,int operation_mode,UINT16 * data)
{
if ((phyaddr % 2)!=0)
{
//exception
//bad address
exception(ADEL,-1);
return false;
}
if (cache_able==true )
{
//load a word from cache.
if (load_halfword_from_cache(vaddr, phyaddr,operation_mode, data))
return true;
}
/*now, cache miss or cache_able=false ,load from ram*/
{
//load a word from ram
if (load_halfword_from_memory(phyaddr, data))
return true;
else
return false;
}
}
/*Get the instruction of virtual address PC. return instruction.
true: mean fetch the instruction(no exception occurs)
false: An exception occurs. */
static boolean cpu_fetch_instruction(UINT32 * instruction,UINT32 phyaddr,boolean cache_able)
{
//UINT32 phyaddr;
//boolean cache_able;
//fprintf(stderr,"start cpu_fetch_instruction()----------------------------------!\n");
//fprintf(stderr,"PC=%x,",PC);
//phyaddr = vaddr2phyaddr(PC,INSTRUCTION_LOAD,&cache_able);
//fprintf(stderr,"phyaddr=%x,",phyaddr);
if (0xffffffff==phyaddr)
{
// exception
fprintf(stderr,"Error vaddr->phyaddr,aborting\n ");
return false;
}
else
{
if ( load_word(PC,phyaddr,cache_able,INSTRUCTION_LOAD,instruction))
{
//fprintf(stderr,"instruction=%x,",instruction);
return true;
}
else
return false;
}
}
/*decode instruciton. jump to different entry.*/
static UINT16 get_op_code (const UINT32 instruction)
{
return ((instruction>>26) & 0x0000003f);
}
static UINT16 get_rs(const UINT32 instruction)
{
return (instruction >> 21 ) & 0x0000001f;
}
static UINT16 get_rt(const UINT32 instruction)
{
return (instruction >> 16 ) & 0x0000001f;
}
static UINT16 get_rd(const UINT32 instruction)
{
return (instruction >> 16 ) & 0x0000001f;
}
static UINT16 get_rd0(const UINT32 instruction)
{
return (instruction >> 11 ) & 0x0000001f;
}
/*sub operation (bit 5-0)*/
static UINT16 get_sub_opcode(const UINT32 instruction)
{
return (instruction & 0x0000003f);
}
static UINT16 get_shft(const UINT32 instruction)
{
return (instruction >> 6 ) & 0x0000001f;
}
static UINT16 get_rw(const UINT32 instruction)
{
return (instruction >> 16 ) & 0x0000001f;
}
static INT16 get_broffset(const UINT32 instruction)
{
/*Notice broffset is a 16 bit signed number.*/
return instruction & 0x0000ffff;
}
static UINT16 get_const_unsigned(const UINT32 instuction)
{
return instuction & 0x0000ffff;
}
static INT16 get_const_signed(const UINT32 instuction)
{
return instuction & 0x0000ffff;
}
static UINT16 get_rb(const UINT32 instruction)
{
return (instruction >> 21 ) & 0x0000001f;
}
static INT16 get_offset(const UINT32 instruction)
{
return instruction & 0x0000ffff;
}
/*all instructions' simualtion--------------------------------- begin(order by opcode)*/
/* opcode=0 sub opcode = 0 sll d,w,shft */
static void sll_simulate(const UINT32 instruction)
{
if ((options.debug_mode==true) && (debug.current_mode==STEP))
{
if ((get_rd0(instruction)==ZERO) && (get_rw(instruction)==ZERO) && (get_shft(instruction)==0))
printf("nop");
else
printf("%s %s,%s,0x%x","sll",reg_table[get_rd0(instruction)],reg_table[get_rw(instruction)], get_shft(instruction));
}
cpu_register[get_rd0(instruction)] = cpu_register[get_rw(instruction)] << get_shft(instruction);
}
/* opcode=0 sub opcode = 1 RI exception*/
/* opcode=0 sub opcode = 2 srl d,w,shft*/
static void srl_simulate(const UINT32 instruction)
{
UINT16 shft;
shft = get_shft(instruction);
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,%s,0x%x","srl",reg_table[get_rd0(instruction)],reg_table[get_rw(instruction)], shft);
if (shft!=0)
{
cpu_register[get_rd0(instruction)] = (cpu_register[get_rw(instruction)] >> shft) & ((1<<(32-shft)) -1 );
}
}
/* opcode=0 sub opcode = 3 */
static void sra_simulate(const UINT32 instruction)
{
UINT16 shft;
shft = get_shft(instruction);
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,%s,0x%x","sra",reg_table[get_rd0(instruction)],reg_table[get_rw(instruction)], shft);
if (shft!=0)
{
if ((cpu_register[get_rw(instruction)] & 0x80000000)==0x80000000)
{ //the highest bit is 1
cpu_register[get_rd0(instruction)] = (cpu_register[get_rw(instruction)] >>shft) | (~((1<<(32-shft))-1));
}
else
cpu_register[get_rd0(instruction)] = (cpu_register[get_rw(instruction)] >>shft) & ((1<<(32-shft))-1) ;
}
}
/* opcode=0 sub opcode = 4 */
static void sllv_simulate(const UINT32 instruction)
{
UINT32 rs;
/* rs=rs%32 */
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,%s,%s","sllv",reg_table[get_rd0(instruction)],reg_table[get_rt(instruction)], reg_table[get_rs(instruction)]);
rs = cpu_register[get_rs(instruction)] & 0x0000001f;
if (rs!=0x00000000)
cpu_register[get_rd0(instruction)] = cpu_register[get_rt(instruction)] << (cpu_register[get_rs(instruction)] & 0x0000001f);
}
/* opcode=0 sub opcode = 5 RI*/
/* opcode=0 sub opcode = 6 srlv d,t,s */
static void srlv_simulate(const UINT32 instruction)
{
UINT32 rs;
/* rs=rs%32 */
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,%s,%s","srlv",reg_table[get_rd0(instruction)],reg_table[get_rt(instruction)], reg_table[get_rs(instruction)]);
rs = cpu_register[get_rs(instruction)] & 0x0000001f;
if (rs!=0x00000000)
cpu_register[get_rd0(instruction)] = cpu_register[get_rt(instruction)] >> ( (cpu_register[get_rs(instruction)] & 0x0000001f) & ((1<<(32-rs))-1) ) ;
}
/* opcode=0 sub opcode = 7 srav d,t,s */
static void srav_simulate(const UINT32 instruction)
{
UINT32 rs;
/* rs=rs%32 */
rs = cpu_register[get_rs(instruction)] & 0x0000001f;
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,%s,%s","srav",reg_table[get_rd0(instruction)],reg_table[get_rt(instruction)], reg_table[rs]);
if (rs!=0x00000000)
{
if ((cpu_register[get_rt(instruction)] & 0x80000000)==0x80000000)
{
cpu_register[get_rd0(instruction)] = (cpu_register[get_rt(instruction)] >>rs) | (~((1<<(32-rs))-1));
}
else
{
cpu_register[get_rd0(instruction)] = (cpu_register[get_rt(instruction)] >>rs) & ((1<<(32-rs))-1) ;
}
}
}
/* opcode=0 sub opcode = 8 jr s */
static void jr_simulate(const UINT32 instruction)
{
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s","jr ", reg_table[get_rs(instruction)]);
delay_state = DELAYING;
delay_pc = cpu_register[get_rs(instruction)] ;
//neednot to save RA register
//cpu_register[RA] = PC + 8;
}
/* opcode=0 sub opcode = 9 jalr d,s */
static void jalr_simulate(const UINT32 instruction)
{
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,%s","jalr",reg_table[get_rd0(instruction)],reg_table[get_rs(instruction)]);
delay_state = DELAYING;
delay_pc = cpu_register[get_rs(instruction)] ;
/* put return address to rd. PC+8(because delay slot)*/
cpu_register[get_rd0(instruction)] = PC + 8;
}
/* opcode=0 sub opcode = 10,11 RI Exception */
/* opcode=0 sub opcode = 12 syscall code */
static void syscall_simulate(const UINT32 instruction)
{
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s","syscall");
//system call exception
exception(SYSCAL,-1);
}
/* opcode=0 sub opcode = 13 break code */
static void break_simulate(const UINT32 instruction)
{
//break exception
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s","break");
exception(BP,-1);
}
/* opcode=0 sub opcode = 14 sdbbp code(MIPS II) ,RI Exception */
/* opcode=0 sub opcode = 15 sync , not implement */
/* opcode=0 sub opcode = 16 mfhi d */
static void mfhi_simulate(const UINT32 instruction)
{
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s","mfhi",reg_table[get_rd0(instruction)]);
cpu_register[get_rd0(instruction)] = hi;
}
/* opcode=0 sub opcode = 17 mthi s */
static void mthi_simulate(const UINT32 instruction)
{
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s","mthi",reg_table[get_rs(instruction)]);
hi = cpu_register[get_rs(instruction)] ;
}
/* opcode=0 sub opcode = 18 mflo d */
static void mflo_simulate(const UINT32 instruction)
{
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s","mflo",reg_table[get_rd0(instruction)]);
cpu_register[get_rd0(instruction)] = lo;
}
/* opcode=0 sub opcode = 19 mtflo s */
static void mtlo_simulate(const UINT32 instruction)
{
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s","mthlo",reg_table[get_rs(instruction)]);
lo = cpu_register[get_rs(instruction)] ;
}
/* opcode=0 sub opcode = 20 dsllv d,t,s MIPS III */
/* opcode=0 sub opcode = RI exception */
/* opcode=0 sub opcode = 22 dsrlv d,t,s MIPS III */
/* opcode=0 sub opcode = 23 dsrav d,t,s MIPS III */
/* opcode=0 sub opcode = 24 mult s,t (signed mult)*/
static void mult_simulate(const UINT32 instruction)
{
INT32 rs,rt;
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,%s","mult",reg_table[get_rs(instruction)], reg_table[get_rt(instruction)]);
rs=(INT32)cpu_register[get_rs(instruction)];
rt=(INT32)cpu_register[get_rt(instruction)];
mult_signed(&hi,&lo, rs, rt);
}
/* opcode=0 sub opcode = 25 multu s,t (unsigned mult)*/
static void multu_simulate(const UINT32 instruction)
{
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,%s","multu",reg_table[get_rs(instruction)], reg_table[get_rt(instruction)]);
mult_unsigned(&hi, &lo, cpu_register[get_rs(instruction)], cpu_register[get_rt(instruction)]);
}
/* opcode=0 sub opcode = 26 div s,t (signed div)*/
static void div_simulate(const UINT32 instruction)
{
INT32 rs,rt;
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,%s","div",reg_table[get_rs(instruction)], reg_table[get_rt(instruction)]);
rs =(INT32) cpu_register[get_rs(instruction)];
rt = (INT32) cpu_register[get_rt(instruction)];
lo = rs /rt;
hi = rs%rt;
}
/* opcode=0 sub opcode = 27 divu s,t (unsigned div)*/
static void divu_simulate(const UINT32 instruction)
{
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,%s","divu",reg_table[get_rs(instruction)], reg_table[get_rt(instruction)]);
lo = cpu_register[get_rs(instruction)]/cpu_register[get_rt(instruction)];
hi = cpu_register[get_rs(instruction)]%cpu_register[get_rt(instruction)];
}
/* opcode=0 sub opcode = 28 dmult s,t MIPS III */
/* opcode=0 sub opcode = 29 dmultu s,t MIPS III */
/* opcode=0 sub opcode = 30 ddiv s,t MIPS III */
/* opcode=0 sub opcode = 31 ddivu s,t MIPS III */
/* opcode=0 sub opcode = 32 add d,s,t */
static void add_simulate(const UINT32 instruction)
{
INT32 rs,rt,sum;
if ((options.debug_mode==true) && (debug.current_mode==STEP))
printf("%s %s,%s,%s","add",reg_table[get_rd0(instruction)] ,reg_table[get_rs(instruction)], reg_table[get_rt(instruction)]);
rs=(INT32)cpu_register[get_rs(instruction)];
rt=(INT32)cpu_register[get_rt(instruction)];
sum = rs+rt;
//printf("rs %x",rs);
//printf("rt %x",rt);
//printf("sum %x",sum);
if (((rs<0) && (rt<0) &(sum>=0)) ||((rs>0) && (rt>0) &(sum<=0)))
{
//an overflow exception
exception(OV,-1);
}
else
{
cpu_register[get_rd0(instruction)] = (UINT32) sum;
//printf(" (UINT32) sum %x", (UINT32) sum);
}
}
/* opcode=0 sub opcode = 33 addu d,s,t */
static void addu_simulate(const UINT32 instruction)
{
//printf("asdfasfd\n");
//printf("get_rd0(instruction) %d\n",instruction );
//printf("get_rd0(instruction) %d\n",get_rd0(instruction));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -