📄 interp.c
字号:
XXX FIXME: eventually, stopping the simulator should be made conditional on a command-line option. */voidunpredictable_action(sim_cpu *cpu, address_word cia){ SIM_DESC sd = CPU_STATE(cpu); sim_io_eprintf(sd, "UNPREDICTABLE: PC = 0x%s\n", pr_addr (cia)); sim_engine_halt (SD, CPU, NULL, cia, sim_stopped, SIM_SIGABRT);}/*-- co-processor support routines ------------------------------------------*/static int UNUSEDCoProcPresent(unsigned int coproc_number){ /* Return TRUE if simulator provides a model for the given co-processor number */ return(0);}voidcop_lw (SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg, unsigned int memword){ switch (coproc_num) { case 1: if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) {#ifdef DEBUG printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword));#endif StoreFPR(coproc_reg,fmt_word,(uword64)memword); FPR_STATE[coproc_reg] = fmt_uninterpreted; break; } default:#if 0 /* this should be controlled by a configuration option */ sim_io_printf(sd,"COP_LW(%d,%d,0x%08X) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,memword,pr_addr(cia));#endif break; } return;}voidcop_ld (SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg, uword64 memword){#ifdef DEBUG printf("DBG: COP_LD: coproc_num = %d, coproc_reg = %d, value = 0x%s : PC = 0x%s\n", coproc_num, coproc_reg, pr_uword64(memword), pr_addr(cia) );#endif switch (coproc_num) { case 1: if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) { StoreFPR(coproc_reg,fmt_uninterpreted,memword); break; } default:#if 0 /* this message should be controlled by a configuration option */ sim_io_printf(sd,"COP_LD(%d,%d,0x%s) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(memword),pr_addr(cia));#endif break; } return;}unsigned intcop_sw (SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg){ unsigned int value = 0; switch (coproc_num) { case 1: if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) { FP_formats hold; hold = FPR_STATE[coproc_reg]; FPR_STATE[coproc_reg] = fmt_word; value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted); FPR_STATE[coproc_reg] = hold; break; } default:#if 0 /* should be controlled by configuration option */ sim_io_printf(sd,"COP_SW(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia));#endif break; } return(value);}uword64cop_sd (SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg){ uword64 value = 0; switch (coproc_num) { case 1: if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT) { value = ValueFPR(coproc_reg,fmt_uninterpreted); break; } default:#if 0 /* should be controlled by configuration option */ sim_io_printf(sd,"COP_SD(%d,%d) at PC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(cia));#endif break; } return(value);}voiddecode_coproc (SIM_DESC sd, sim_cpu *cpu, address_word cia, unsigned int instruction){ int coprocnum = ((instruction >> 26) & 3); switch (coprocnum) { case 0: /* standard CPU control and cache registers */ { int code = ((instruction >> 21) & 0x1F); int rt = ((instruction >> 16) & 0x1F); int rd = ((instruction >> 11) & 0x1F); int tail = instruction & 0x3ff; /* R4000 Users Manual (second edition) lists the following CP0 instructions: CODE><-RT><RD-><--TAIL---> DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000) DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000) MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000) MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000) TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001) TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010) TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110) TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000) CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii) ERET Exception return (VR4100 = 01000010000000000000000000011000) */ if (((code == 0x00) || (code == 0x04) /* MFC0 / MTC0 */ || (code == 0x01) || (code == 0x05)) /* DMFC0 / DMTC0 */ && tail == 0) { /* Clear double/single coprocessor move bit. */ code &= ~1; /* M[TF]C0 (32 bits) | DM[TF]C0 (64 bits) */ switch (rd) /* NOTEs: Standard CP0 registers */ { /* 0 = Index R4000 VR4100 VR4300 */ /* 1 = Random R4000 VR4100 VR4300 */ /* 2 = EntryLo0 R4000 VR4100 VR4300 */ /* 3 = EntryLo1 R4000 VR4100 VR4300 */ /* 4 = Context R4000 VR4100 VR4300 */ /* 5 = PageMask R4000 VR4100 VR4300 */ /* 6 = Wired R4000 VR4100 VR4300 */ /* 8 = BadVAddr R4000 VR4100 VR4300 */ /* 9 = Count R4000 VR4100 VR4300 */ /* 10 = EntryHi R4000 VR4100 VR4300 */ /* 11 = Compare R4000 VR4100 VR4300 */ /* 12 = SR R4000 VR4100 VR4300 */#ifdef SUBTARGET_R3900 case 3: /* 3 = Config R3900 */ case 7: /* 7 = Cache R3900 */ case 15: /* 15 = PRID R3900 */ /* ignore */ break; case 8: /* 8 = BadVAddr R4000 VR4100 VR4300 */ if (code == 0x00) GPR[rt] = (signed_word) (signed_address) COP0_BADVADDR; else COP0_BADVADDR = GPR[rt]; break;#endif /* SUBTARGET_R3900 */ case 12: if (code == 0x00) GPR[rt] = SR; else SR = GPR[rt]; break; /* 13 = Cause R4000 VR4100 VR4300 */ case 13: if (code == 0x00) GPR[rt] = CAUSE; else CAUSE = GPR[rt]; break; /* 14 = EPC R4000 VR4100 VR4300 */ case 14: if (code == 0x00) GPR[rt] = (signed_word) (signed_address) EPC; else EPC = GPR[rt]; break; /* 15 = PRId R4000 VR4100 VR4300 */#ifdef SUBTARGET_R3900 /* 16 = Debug */ case 16: if (code == 0x00) GPR[rt] = Debug; else Debug = GPR[rt]; break;#else /* 16 = Config R4000 VR4100 VR4300 */ case 16: if (code == 0x00) GPR[rt] = C0_CONFIG; else C0_CONFIG = GPR[rt]; break;#endif#ifdef SUBTARGET_R3900 /* 17 = Debug */ case 17: if (code == 0x00) GPR[rt] = DEPC; else DEPC = GPR[rt]; break;#else /* 17 = LLAddr R4000 VR4100 VR4300 */#endif /* 18 = WatchLo R4000 VR4100 VR4300 */ /* 19 = WatchHi R4000 VR4100 VR4300 */ /* 20 = XContext R4000 VR4100 VR4300 */ /* 26 = PErr or ECC R4000 VR4100 VR4300 */ /* 27 = CacheErr R4000 VR4100 */ /* 28 = TagLo R4000 VR4100 VR4300 */ /* 29 = TagHi R4000 VR4100 VR4300 */ /* 30 = ErrorEPC R4000 VR4100 VR4300 */ if (STATE_VERBOSE_P(SD)) sim_io_eprintf (SD, "Warning: PC 0x%lx:interp.c decode_coproc DEADC0DE\n", (unsigned long)cia); GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */ /* CPR[0,rd] = GPR[rt]; */ default: if (code == 0x00) GPR[rt] = (signed_word) (signed32) COP0_GPR[rd]; else COP0_GPR[rd] = GPR[rt];#if 0 if (code == 0x00) sim_io_printf(sd,"Warning: MFC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt,rd, (unsigned)cia); else sim_io_printf(sd,"Warning: MTC0 %d,%d ignored, PC=%08x (architecture specific)\n",rt,rd, (unsigned)cia);#endif } } else if (code == 0x10 && (tail & 0x3f) == 0x18) { /* ERET */ if (SR & status_ERL) { /* Oops, not yet available */ sim_io_printf(sd,"Warning: ERET when SR[ERL] set not handled yet"); PC = EPC; SR &= ~status_ERL; } else { PC = EPC; SR &= ~status_EXL; } } else if (code == 0x10 && (tail & 0x3f) == 0x10) { /* RFE */#ifdef SUBTARGET_R3900 /* TX39: Copy IEp/KUp -> IEc/KUc, and IEo/KUo -> IEp/KUp */ /* shift IE/KU history bits right */ SR = LSMASKED32(SR, 31, 4) | LSINSERTED32(LSEXTRACTED32(SR, 5, 2), 3, 0); /* TODO: CACHE register */#endif /* SUBTARGET_R3900 */ } else if (code == 0x10 && (tail & 0x3f) == 0x1F) { /* DERET */ Debug &= ~Debug_DM; DELAYSLOT(); DSPC = DEPC; } else sim_io_eprintf(sd,"Unrecognised COP0 instruction 0x%08X at PC = 0x%s : No handler present\n",instruction,pr_addr(cia)); /* TODO: When executing an ERET or RFE instruction we should clear LLBIT, to ensure that any out-standing atomic read/modify/write sequence fails. */ } break; case 2: /* co-processor 2 */ { int handle = 0; if(! handle) { sim_io_eprintf(sd, "COP2 instruction 0x%08X at PC = 0x%s : No handler present\n", instruction,pr_addr(cia)); } } break; case 1: /* should not occur (FPU co-processor) */ case 3: /* should not occur (FPU co-processor) */ SignalException(ReservedInstruction,instruction); break; } return;}/* This code copied from gdb's utils.c. Would like to share this code, but don't know of a common place where both could get to it. *//* Temporary storage using circular buffer */#define NUMCELLS 16#define CELLSIZE 32static char*get_cell (void){ static char buf[NUMCELLS][CELLSIZE]; static int cell=0; if (++cell>=NUMCELLS) cell=0; return buf[cell];} /* Print routines to handle variable size regs, etc *//* Eliminate warning from compiler on 32-bit systems */static int thirty_two = 32; char* pr_addr(addr) SIM_ADDR addr;{ char *paddr_str=get_cell(); switch (sizeof(addr)) { case 8: sprintf(paddr_str,"%08lx%08lx", (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff)); break; case 4: sprintf(paddr_str,"%08lx",(unsigned long)addr); break; case 2: sprintf(paddr_str,"%04x",(unsigned short)(addr&0xffff)); break; default: sprintf(paddr_str,"%x",addr); } return paddr_str;}char* pr_uword64(addr) uword64 addr;{ char *paddr_str=get_cell(); sprintf(paddr_str,"%08lx%08lx", (unsigned long)(addr>>thirty_two),(unsigned long)(addr&0xffffffff)); return paddr_str;}voidmips_core_signal (SIM_DESC sd, sim_cpu *cpu, sim_cia cia, unsigned map, int nr_bytes, address_word addr, transfer_type transfer, sim_core_signals sig){ const char *copy = (transfer == read_transfer ? "read" : "write"); address_word ip = CIA_ADDR (cia); switch (sig) { case sim_core_unmapped_signal: sim_io_eprintf (sd, "mips-core: %d byte %s to unmapped address 0x%lx at 0x%lx\n", nr_bytes, copy, (unsigned long) addr, (unsigned long) ip); COP0_BADVADDR = addr; SignalExceptionDataReference(); break; case sim_core_unaligned_signal: sim_io_eprintf (sd, "mips-core: %d byte %s to unaligned address 0x%lx at 0x%lx\n", nr_bytes, copy, (unsigned long) addr, (unsigned long) ip); COP0_BADVADDR = addr; if(transfer == read_transfer) SignalExceptionAddressLoad(); else SignalExceptionAddressStore(); break; default: sim_engine_abort (sd, cpu, cia, "mips_core_signal - internal error - bad switch"); }}voidmips_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word cia){ ASSERT(cpu != NULL); if(cpu->exc_suspended > 0) sim_io_eprintf(sd, "Warning, nested exception triggered (%d)\n", cpu->exc_suspended); PC = cia; memcpy(cpu->exc_trigger_registers, cpu->registers, sizeof(cpu->exc_trigger_registers));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -