diff options
Diffstat (limited to 'sim/mips/interp.c')
-rw-r--r-- | sim/mips/interp.c | 602 |
1 files changed, 534 insertions, 68 deletions
diff --git a/sim/mips/interp.c b/sim/mips/interp.c index 4c9747d..ba3d6e5 100644 --- a/sim/mips/interp.c +++ b/sim/mips/interp.c @@ -39,12 +39,16 @@ code on the hardware. #include "sim-assert.h" #include "sim-hw.h" +#if WITH_IGEN +#include "itable.h" +#endif + /* start-sanitize-sky */ #ifdef TARGET_SKY #include "sky-vu.h" #include "sky-vpe.h" #include "sky-libvpe.h" -#include "sky-pke.h" +#include "sky-vif.h" #include "idecode.h" #include "sky-gdb.h" #endif @@ -159,6 +163,8 @@ static void ColdReset PARAMS((SIM_DESC sd)); #ifdef TARGET_SKY #undef MEM_SIZE #define MEM_SIZE (16 << 20) /* 16 MB */ +#undef MONITOR_SIZE +#define MONITOR_SIZE 0x100000 /* 1MB */ #endif /* end-sanitize-sky */ @@ -168,6 +174,10 @@ FILE *tracefh = NULL; static void open_trace PARAMS((SIM_DESC sd)); #endif /* TRACE */ +#if WITH_IGEN +static const char * get_insn_name (sim_cpu *, int); +#endif + /* simulation target board. NULL=canonical */ static char* board = NULL; @@ -329,7 +339,7 @@ interrupt_event (SIM_DESC sd, void *data) if (SR & status_IE) { interrupt_pending = 0; - SignalExceptionInterrupt (); + SignalExceptionInterrupt (1); /* interrupt "1" */ } else if (!interrupt_pending) sim_events_schedule (sd, 1, interrupt_event, data); @@ -367,6 +377,12 @@ sim_open (kind, cb, abfd, argv) STATE_WATCHPOINTS (sd)->sizeof_pc = sizeof (PC); STATE_WATCHPOINTS (sd)->interrupt_handler = interrupt_event; +#if WITH_IGEN + /* Initialize the mechanism for doing insn profiling. */ + CPU_INSN_NAME (cpu) = get_insn_name; + CPU_MAX_INSNS (cpu) = nr_itable_entries; +#endif + STATE = 0; if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) @@ -431,6 +447,10 @@ sim_open (kind, cb, abfd, argv) { /* match VIRTUAL memory layout of JMR-TX3904 board */ + /* --- environment --- */ + + STATE_ENVIRONMENT (sd) = OPERATING_ENVIRONMENT; + /* --- memory --- */ /* ROM: 0x9FC0_0000 - 0x9FFF_FFFF and 0xBFC0_0000 - 0xBFFF_FFFF */ @@ -451,18 +471,38 @@ sim_open (kind, cb, abfd, argv) 32 * 1024 * 1024, /* 32 MB */ 0xA8000000); + /* Dummy memory regions for unsimulated devices */ + + sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFFE010, 0x00c); /* EBIF */ + sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFF9000, 0x200); /* EBIF */ + sim_do_commandf (sd, "memory alias 0x%lx@1,0x%lx", 0xFFFFF500, 0x300); /* PIO */ + /* --- simulated devices --- */ sim_hw_parse (sd, "/tx3904irc@0xffffc000/reg 0xffffc000 0x20"); sim_hw_parse (sd, "/tx3904cpu"); sim_hw_parse (sd, "/tx3904tmr@0xfffff000/reg 0xfffff000 0x100"); sim_hw_parse (sd, "/tx3904tmr@0xfffff100/reg 0xfffff100 0x100"); sim_hw_parse (sd, "/tx3904tmr@0xfffff200/reg 0xfffff200 0x100"); - + sim_hw_parse (sd, "/tx3904sio@0xfffff300/reg 0xfffff300 0x100"); + { + /* FIXME: poking at dv-sockser internals, use tcp backend if + --sockser_addr option was given.*/ + extern char* sockser_addr; + if(sockser_addr == NULL) + sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend stdio"); + else + sim_hw_parse (sd, "/tx3904sio@0xfffff300/backend tcp"); + } + sim_hw_parse (sd, "/tx3904sio@0xfffff400/reg 0xfffff400 0x100"); + sim_hw_parse (sd, "/tx3904sio@0xfffff400/backend stdio"); + /* -- device connections --- */ sim_hw_parse (sd, "/tx3904irc > ip level /tx3904cpu"); sim_hw_parse (sd, "/tx3904tmr@0xfffff000 > int tmr0 /tx3904irc"); sim_hw_parse (sd, "/tx3904tmr@0xfffff100 > int tmr1 /tx3904irc"); sim_hw_parse (sd, "/tx3904tmr@0xfffff200 > int tmr2 /tx3904irc"); + sim_hw_parse (sd, "/tx3904sio@0xfffff300 > int sio0 /tx3904irc"); + sim_hw_parse (sd, "/tx3904sio@0xfffff400 > int sio1 /tx3904irc"); /* add PAL timer & I/O module */ if(! strcmp(board, BOARD_JMR3904_PAL)) @@ -559,11 +599,14 @@ sim_open (kind, cb, abfd, argv) else cpu->register_widths[rn] = 0; } - /* start-sanitize-r5900 */ + /* start-sanitize-r5900 */ /* set the 5900 "upper" registers to 64 bits */ - for( rn = LAST_EMBED_REGNUM+1; rn < NUM_REGS; rn++) + for( rn = LAST_EMBED_REGNUM+1; rn < FIRST_COP0_REG; rn++) cpu->register_widths[rn] = 64; + + for( rn = FIRST_COP0_REG; rn < NUM_REGS; rn++) + cpu->register_widths[rn] = 32; /* end-sanitize-r5900 */ /* start-sanitize-sky */ @@ -601,8 +644,12 @@ sim_open (kind, cb, abfd, argv) HALT_INSTRUCTION /* BREAK */ }; H2T (halt[0]); H2T (halt[1]); + sim_write (sd, 0x80000000, (char *) halt, sizeof (halt)); sim_write (sd, 0x80000180, (char *) halt, sizeof (halt)); + sim_write (sd, 0x80000200, (char *) halt, sizeof (halt)); + sim_write (sd, 0xBFC00200, (char *) halt, sizeof (halt)); sim_write (sd, 0xBFC00380, (char *) halt, sizeof (halt)); + sim_write (sd, 0xBFC00400, (char *) halt, sizeof (halt)); } @@ -667,6 +714,31 @@ sim_open (kind, cb, abfd, argv) } } + + /* start-sanitize-sky */ +#ifdef TARGET_SKY + /* Default TLB initialization... */ + +#define KPAGEMASK 0x001fe000 +#define PAGE_MASK_4K 0x00000000 +#define PAGE_MASK_16K 0x00006000 +#define PAGE_MASK_64K 0x0001e000 +#define PAGE_MASK_256K 0x0007e000 +#define PAGE_MASK_1M 0x001fe000 +#define PAGE_MASK_4M 0x007fe000 +#define PAGE_MASK_16M 0x01ffe000 + +#define SET_TLB(index, page_mask, entry_hi, entry_lo0, entry_lo1) \ + TLB[index].mask = page_mask; \ + TLB[index].hi = entry_hi; \ + TLB[index].lo0 = entry_lo0; \ + TLB[index].lo1 = entry_lo1 + + SET_TLB(0, PAGE_MASK_16M, 0x00000000, 0x0000001e, 0x0004001e);/*0-32M*/ + +#endif /* TARGET_SKY */ + /* end-sanitize-sky */ + return sd; } @@ -684,6 +756,15 @@ open_trace(sd) } #endif /* TRACE */ +#if WITH_IGEN +/* Return name of an insn, used by insn profiling. */ +static const char * +get_insn_name (sim_cpu *cpu, int i) +{ + return itable[i].name; +} +#endif + void sim_close (sd, quitting) SIM_DESC sd; @@ -821,6 +902,38 @@ sim_store_register (sd,rn,memory,length) HI1 = T2H_8(*(unsigned64*)memory); return 8; } + + if (rn >= FIRST_COP0_REG && rn < (FIRST_COP0_REG+NUM_COP0_REGS)) + { + switch (rn - FIRST_COP0_REG) + { + case 12: /* Status */ + case 13: /* Cause */ + return -1; /* Already done in regular register set */ + case 14: + EPC = T2H_4(*((unsigned32*) memory)); + break; + case 16: + C0_CONFIG = T2H_4(*((unsigned32*) memory)); + break; + case 17: /* Debug */ + Debug = T2H_4(*((unsigned32*) memory)); + break; + case 18: /* Perf */ + COP0_GPR[rn - FIRST_COP0_REG + 7] = T2H_4(*((unsigned32*) memory)); + break; + case 19: /* TagLo */ + case 20: /* TagHi */ + case 21: /* ErrorEPC */ + COP0_GPR[rn - FIRST_COP0_REG + 9] = T2H_4(*((unsigned32*) memory)); + break; + default: + COP0_GPR[rn - FIRST_COP0_REG] = T2H_4(*((unsigned32*) memory)); + break; + } + + return 4; + } /* end-sanitize-r5900 */ /* start-sanitize-sky */ @@ -831,6 +944,10 @@ sim_store_register (sd,rn,memory,length) if( rn < NUM_VU_REGS ) { +#ifdef TARGET_SKY_B + sim_io_eprintf( sd, "Invalid VU register (register store ignored)\n" ); + return 0; +#else if (rn < NUM_VU_INTEGER_REGS) return write_vu_int_reg (&(vu0_device.regs), rn, memory); else if (rn >= FIRST_VEC_REG) @@ -842,24 +959,34 @@ sim_store_register (sd,rn,memory,length) else switch (rn - NUM_VU_INTEGER_REGS) { case 0: - return write_vu_special_reg (&vu0_device, VU_REG_CIA, - memory); - case 1: - return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MR, - memory); - case 2: /* VU0 has no P register */ + return write_vu_special_reg (&vu0_device, VU_REG_CIA, memory); + + case 1: /* Can't write TPC register */ + case 2: /* or VPU_STAT */ + case 4: /* or MAC */ + case 9: /* VU0 has no P register */ return 4; + case 3: - return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MI, - memory); - case 4: - return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MQ, - memory); + return write_vu_misc_reg(&(vu0_device.regs), VU_REG_MST, memory); + case 5: + return write_vu_misc_reg(&(vu0_device.regs), VU_REG_MCP, memory); + case 6: + return write_vu_special_reg (&vu0_device, VU_REG_CMSAR0, memory); + case 7: + return write_vu_special_reg (&vu0_device, VU_REG_FBRST, memory); + case 8: + return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MR, memory); + case 10: + return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MI, memory); + case 11: + return write_vu_misc_reg (&(vu0_device.regs), VU_REG_MQ, memory); default: return write_vu_acc_reg (&(vu0_device.regs), - rn - (NUM_VU_INTEGER_REGS + 5), + rn - (NUM_VU_INTEGER_REGS + 12), memory); } +#endif /* ! TARGET_SKY_B */ } rn = rn - NUM_VU_REGS; @@ -877,23 +1004,35 @@ sim_store_register (sd,rn,memory,length) else switch (rn - NUM_VU_INTEGER_REGS) { case 0: - return write_vu_special_reg (&vu1_device, VU_REG_CIA, - memory); - case 1: - return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MR, - memory); - case 2: - return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MP, - memory); + return write_vu_special_reg (&vu1_device, VU_REG_CIA, memory); + + case 1: /* Can't write TPC register */ + case 2: /* or VPU_STAT */ + case 4: /* or MAC */ + case 7: /* VU1 has no FBRST register */ + return 4; + case 3: - return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MI, - memory); - case 4: - return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MQ, - memory); + return write_vu_misc_reg(&(vu1_device.regs), VU_REG_MST, memory); + case 5: + return write_vu_misc_reg(&(vu1_device.regs), VU_REG_MCP, memory); + case 6: /* CMSAR1 is actually part of VU0 */ +#ifdef TARGET_SKY_B + return 0; +#else + return write_vu_special_reg (&vu0_device, VU_REG_CMSAR1, memory); +#endif /* ! TARGET_SKY_B */ + case 8: + return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MR, memory); + case 9: + return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MP, memory); + case 10: + return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MI, memory); + case 11: + return write_vu_misc_reg (&(vu1_device.regs), VU_REG_MQ, memory); default: return write_vu_acc_reg (&(vu1_device.regs), - rn - (NUM_VU_INTEGER_REGS + 5), + rn - (NUM_VU_INTEGER_REGS + 12), memory); } } @@ -902,13 +1041,18 @@ sim_store_register (sd,rn,memory,length) if (rn < NUM_VIF_REGS) { +#ifdef TARGET_SKY_B + sim_io_eprintf( sd, "Invalid VIF register (register store ignored)\n" ); + return 0; +#else if (rn < NUM_VIF_REGS-1) - return write_pke_reg (&pke0_device, rn, memory); + return write_vif_reg (&vif0_device, rn, memory); else { sim_io_eprintf( sd, "Can't write vif0_pc (store ignored)\n" ); return 0; } +#endif /* ! TARGET_SKY_B */ } rn -= NUM_VIF_REGS; /* VIF1 registers are last */ @@ -916,7 +1060,7 @@ sim_store_register (sd,rn,memory,length) if (rn < NUM_VIF_REGS) { if (rn < NUM_VIF_REGS-1) - return write_pke_reg (&pke1_device, rn, memory); + return write_vif_reg (&vif1_device, rn, memory); else { sim_io_eprintf( sd, "Can't write vif1_pc (store ignored)\n" ); @@ -996,6 +1140,38 @@ sim_fetch_register (sd,rn,memory,length) *((unsigned64*)memory) = H2T_8(HI1); return 8; } + + if (rn >= FIRST_COP0_REG && rn < (FIRST_COP0_REG+NUM_COP0_REGS)) + { + switch (rn - FIRST_COP0_REG) + { + case 12: /* Status */ + case 13: /* Cause */ + return -1; /* Already done in regular register set */ + case 14: + *((unsigned32*) memory) = H2T_4(EPC); + break; + case 16: + *((unsigned32*) memory) = H2T_4(C0_CONFIG); + break; + case 17: /* Debug */ + *((unsigned32*) memory) = H2T_4(Debug); + break; + case 18: /* Perf */ + *((unsigned32*) memory) = H2T_4(COP0_GPR[rn - FIRST_COP0_REG + 7]); + break; + case 19: /* TagLo */ + case 20: /* TagHi */ + case 21: /* ErrorEPC */ + *((unsigned32*) memory) = H2T_4(COP0_GPR[rn - FIRST_COP0_REG + 9]); + break; + default: + *((unsigned32*) memory) = H2T_4(COP0_GPR[rn - FIRST_COP0_REG]); + break; + } + + return 4; + } /* end-sanitize-r5900 */ /* start-sanitize-sky */ @@ -1006,6 +1182,10 @@ sim_fetch_register (sd,rn,memory,length) if (rn < NUM_VU_REGS) { +#ifdef TARGET_SKY_B + sim_io_eprintf( sd, "Invalid VU register (register fetch ignored)\n" ); + return 0; +#else if (rn < NUM_VU_INTEGER_REGS) return read_vu_int_reg (&(vu0_device.regs), rn, memory); else if (rn >= FIRST_VEC_REG) @@ -1017,24 +1197,36 @@ sim_fetch_register (sd,rn,memory,length) else switch (rn - NUM_VU_INTEGER_REGS) { case 0: - return read_vu_special_reg(&vu0_device, VU_REG_CIA, memory); + return read_vu_special_reg (&vu0_device, VU_REG_CIA, memory); case 1: - return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MR, - memory); - case 2: /* VU0 has no P register */ - *((int *) memory) = 0; - return 4; + return read_vu_misc_reg(&(vu0_device.regs), VU_REG_MTPC, memory); + case 2: + return read_vu_special_reg (&vu0_device, VU_REG_STAT, memory); case 3: - return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MI, - memory); + return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MST, memory); case 4: - return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MQ, - memory); + return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MMC, memory); + case 5: + return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MCP, memory); + case 6: + return read_vu_special_reg (&vu0_device, VU_REG_CMSAR0, memory); + case 7: + return read_vu_special_reg (&vu0_device, VU_REG_FBRST, memory); + case 8: + return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MR, memory); + case 9: /* VU0 has no P register */ + *((int *) memory) = 0; + return 4; + case 10: + return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MI, memory); + case 11: + return read_vu_misc_reg (&(vu0_device.regs), VU_REG_MQ, memory); default: return read_vu_acc_reg (&(vu0_device.regs), - rn - (NUM_VU_INTEGER_REGS + 5), + rn - (NUM_VU_INTEGER_REGS + 12), memory); } +#endif /* ! TARGET_SKY_B */ } rn -= NUM_VU_REGS; /* VU1 registers are next */ @@ -1052,22 +1244,37 @@ sim_fetch_register (sd,rn,memory,length) else switch (rn - NUM_VU_INTEGER_REGS) { case 0: - return read_vu_special_reg(&vu1_device, VU_REG_CIA, memory); + return read_vu_special_reg (&vu1_device, VU_REG_CIA, memory); case 1: - return read_vu_misc_reg (&(vu1_device.regs), - VU_REG_MR, memory); + return read_vu_misc_reg(&(vu1_device.regs), VU_REG_MTPC, memory); case 2: - return read_vu_misc_reg (&(vu1_device.regs), - VU_REG_MP, memory); + return read_vu_special_reg (&vu1_device, VU_REG_STAT, memory); case 3: - return read_vu_misc_reg (&(vu1_device.regs), - VU_REG_MI, memory); + return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MST, memory); case 4: - return read_vu_misc_reg (&(vu1_device.regs), - VU_REG_MQ, memory); + return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MMC, memory); + case 5: + return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MCP, memory); + case 6: /* CMSAR1 is actually from VU0 */ +#ifdef TARGET_SKY_B + return 0; +#else + return read_vu_special_reg (&vu0_device, VU_REG_CMSAR1, memory); +#endif /* ! TARGET_SKY_B */ + case 7: /* VU1 has no FBRST register */ + *((int *) memory) = 0; + return 4; + case 8: + return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MR, memory); + case 9: + return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MP, memory); + case 10: + return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MI, memory); + case 11: + return read_vu_misc_reg (&(vu1_device.regs), VU_REG_MQ, memory); default: return read_vu_acc_reg (&(vu1_device.regs), - rn - (NUM_VU_INTEGER_REGS + 5), + rn - (NUM_VU_INTEGER_REGS + 12), memory); } } @@ -1076,12 +1283,17 @@ sim_fetch_register (sd,rn,memory,length) if (rn < NUM_VIF_REGS) { +#ifdef TARGET_SKY_B + sim_io_eprintf( sd, "Invalid VIF register (register fetch ignored)\n" ); + return 0; +#else if (rn < NUM_VIF_REGS-2) - return read_pke_reg (&pke0_device, rn, memory); + return read_vif_reg (&vif0_device, rn, memory); else if (rn == NUM_VIF_REGS-2) - return read_pke_pc (&pke0_device, memory); + return read_vif_pc (&vif0_device, memory); else - return read_pke_pcx (&pke0_device, memory); + return read_vif_pcx (&vif0_device, memory); +#endif /* ! TARGET_SKY_B */ } rn -= NUM_VIF_REGS; /* VIF1 registers are last */ @@ -1089,11 +1301,11 @@ sim_fetch_register (sd,rn,memory,length) if (rn < NUM_VIF_REGS) { if (rn < NUM_VIF_REGS-2) - return read_pke_reg (&pke1_device, rn, memory); + return read_vif_reg (&vif1_device, rn, memory); else if (rn == NUM_VIF_REGS-2) - return read_pke_pc (&pke1_device, memory); + return read_vif_pc (&vif1_device, memory); else - return read_pke_pcx (&pke1_device, memory); + return read_vif_pcx (&vif1_device, memory); } sim_io_eprintf( sd, "Invalid VU register (register fetch ignored)\n" ); @@ -1205,7 +1417,7 @@ fetch_str (sd, addr) } /* Simple monitor interface (currently setup for the IDT and PMON monitors) */ -static void +void sim_monitor (SIM_DESC sd, sim_cpu *cpu, address_word cia, @@ -1715,6 +1927,259 @@ ColdReset (SIM_DESC sd) } } + + +/* start-sanitize-sky */ +#ifdef TARGET_SKY + +/* See ch. 5 of the 5900 Users' Guide. */ +void +signal_exception (SIM_DESC sd, + sim_cpu *cpu, + address_word cia, + int cause, ...) +{ + /* int vector; */ + +#ifdef DEBUG + sim_io_printf(sd,"DBG: SignalException(%d) PC = 0x%s\n",cause,pr_addr(cia)); +#endif /* DEBUG */ + + /* Ensure that any active atomic read/modify/write operation will fail: */ + LLBIT = 0; + + /* First, handle any simulator specific magic exceptions. These are not "real" exceptions, but + are exceptions which the simulator uses to implement different features. */ + + switch (cause) { + + case SimulatorFault: + { + va_list ap; + char *msg; + va_start(ap,cause); + msg = va_arg(ap,char *); + va_end(ap); + sim_engine_abort (SD, CPU, NULL_CIA, + "FATAL: Simulator error \"%s\"\n",msg); + } + + case DebugBreakPoint : + if (! (Debug & Debug_DM)) + { + if (INDELAYSLOT()) + { + CANCELDELAYSLOT(); + + Debug |= Debug_DBD; /* signaled from within in delay slot */ + DEPC = cia - 4; /* reference the branch instruction */ + } + else + { + Debug &= ~Debug_DBD; /* not signaled from within a delay slot */ + DEPC = cia; + } + + Debug |= Debug_DM; /* in debugging mode */ + Debug |= Debug_DBp; /* raising a DBp exception */ + PC = 0xBFC00200; + sim_engine_restart (SD, CPU, NULL, NULL_CIA); + } + break; + + case ReservedInstruction : + { + va_list ap; + unsigned int instruction; + va_start(ap,cause); + instruction = va_arg(ap,unsigned int); + va_end(ap); + /* Provide simple monitor support using ReservedInstruction + exceptions. The following code simulates the fixed vector + entry points into the IDT monitor by causing a simulator + trap, performing the monitor operation, and returning to + the address held in the $ra register (standard PCS return + address). This means we only need to pre-load the vector + space with suitable instruction values. For systems were + actual trap instructions are used, we would not need to + perform this magic. */ + if ((instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTION) + { + sim_monitor (SD, CPU, cia, ((instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK) ); + /* NOTE: This assumes that a branch-and-link style + instruction was used to enter the vector (which is the + case with the current IDT monitor). */ + sim_engine_restart (SD, CPU, NULL, RA); + } + /* Look for the mips16 entry and exit instructions, and + simulate a handler for them. */ + else if ((cia & 1) != 0 + && (instruction & 0xf81f) == 0xe809 + && (instruction & 0x0c0) != 0x0c0) + { + mips16_entry (SD, CPU, cia, instruction); + sim_engine_restart (sd, NULL, NULL, NULL_CIA); + } + /* else fall through to normal exception processing */ + sim_io_eprintf(sd,"ReservedInstruction at PC = 0x%s\n", pr_addr (cia)); + } + } + + /* Now we have the code for processing "real" exceptions. */ + + if (is5900Level2Exception(cause)) { + switch(cause) { + case NMIReset: + cause_set_EXC2(1); + break; + default: + sim_engine_abort (SD, CPU, NULL_CIA, + "FATAL: Unexpected level 2 exception %d\n", cause); + } + if (STATE & simDELAYSLOT) + { + STATE &= ~simDELAYSLOT; + COP0_ERROREPC = (cia - 4); /* reference the branch instruction */ + CAUSE |= cause_BD2; + } + else + { + COP0_ERROREPC = cia; + CAUSE &= ~cause_BD2; + } + + SR |= status_ERL; + + if (cause == NMIReset) + PC = 0xBFC0000; + else + { + ASSERT(0); /* At the moment, COUNTER, DEBUG never generated. */ + } + sim_engine_restart (SD, CPU, NULL, PC); + } else { + /* A level 1 exception. */ + int refill, vector_offset; + + cause_set_EXC(cause); + if (SR & status_EXL) + vector_offset = 0x180; + else + { + if (cause == TLBLoad || cause == TLBStore) { + va_list ap; + va_start(ap, cause); + refill = va_arg(ap,int); + va_end(ap); + } + + if (STATE & simDELAYSLOT) + { + STATE &= ~simDELAYSLOT; + CAUSE |= cause_BD; + COP0_EPC = (cia - 4); /* reference the branch instruction */ + } + else + { + COP0_EPC = cia; + CAUSE &= ~cause_BD; + } + + SR |= status_EXL; + + if ((cause == TLBLoad || cause == TLBStore) && refill == TLB_REFILL) + vector_offset = 0x000; + else if (cause == Interrupt) + vector_offset = 0x200; + else + vector_offset = 0x180; + + if (SR & status_BEV) + PC = (signed)0xBFC00200 + vector_offset; + else + PC = (signed)0x80000000 + vector_offset; + } + + /* Now, handle the exception. */ + switch (cause) + { + case Interrupt: + { + va_list ap; + unsigned int level; + va_start(ap, cause); + level = va_arg(ap,unsigned int); + va_end(ap); + /* Interrupts arrive during event processing, no need to restart. + Hardware interrupts on sky target are INT1 and INT2. */ + if ( level == 1 ) + CAUSE |= cause_IP3; /* bit 11 */ + else if ( level == 2 ) + CAUSE |= cause_IP7; /* bit 15 */ + else + sim_engine_abort (SD, CPU, NULL_CIA, + "FATAL: Unexpected interrupt level %d\n", level); + return; + } + + case NMIReset: + ASSERT(0); /* NMIReset is a level 0 exception. */ + return; + + case AddressLoad: + case AddressStore: + case InstructionFetch: + case DataReference: + /* The following is so that the simulator will continue from the + exception address on breakpoint operations. */ + PC = COP0_EPC; + sim_engine_halt (SD, CPU, NULL, NULL_CIA, + sim_stopped, SIM_SIGBUS); + break; + + case ReservedInstruction: + case CoProcessorUnusable: + PC = COP0_EPC; + sim_engine_halt (SD, CPU, NULL, NULL_CIA, + sim_stopped, SIM_SIGILL); + break; + + case IntegerOverflow: + case FPE: + PC = COP0_EPC; + sim_engine_halt (SD, CPU, NULL, NULL_CIA, + sim_stopped, SIM_SIGFPE); + break; + + case TLBModification: + case TLBLoad: + case TLBStore: + case BreakPoint: + case SystemCall: + case Trap: + sim_engine_restart (SD, CPU, NULL, PC); + break; + + case Watch: + PC = COP0_EPC; + sim_engine_halt (SD, CPU, NULL, NULL_CIA, + sim_stopped, SIM_SIGTRAP); + break; + + default : /* Unknown internal exception */ + PC = COP0_EPC; + sim_engine_halt (SD, CPU, NULL, NULL_CIA, + sim_stopped, SIM_SIGABRT); + break; + + } + } + return; +} + +#else /* TARGET_SKY */ +/* end-sanitize-sky */ + /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */ /* Signal an exception condition. This will result in an exception that aborts the instruction. The instruction operation pseudocode @@ -1928,6 +2393,11 @@ signal_exception (SIM_DESC sd, return; } +/* start-sanitize-sky */ +#endif /* ! TARGET_SKY */ +/* end-sanitize-sky */ + + #if defined(WARN_RESULT) /* Description from page A-26 of the "MIPS IV Instruction Set" manual (revision 3.1) */ /* This function indicates that the result of the operation is @@ -3082,7 +3552,7 @@ cop_ld (SIM_DESC sd, /* start-sanitize-sky */ -#ifdef TARGET_SKY +#if defined(TARGET_SKY) && !defined(TARGET_SKY_B) void cop_lq (SIM_DESC sd, sim_cpu *cpu, @@ -3183,7 +3653,7 @@ cop_sd (SIM_DESC sd, /* start-sanitize-sky */ -#ifdef TARGET_SKY +#if defined(TARGET_SKY) && !defined(TARGET_SKY_B) unsigned128 cop_sq (SIM_DESC sd, sim_cpu *cpu, @@ -3423,7 +3893,7 @@ decode_coproc (SIM_DESC sd, int handle = 0; /* start-sanitize-sky */ -#ifdef TARGET_SKY +#if defined(TARGET_SKY) && !defined(TARGET_SKY_B) /* On the R5900, this refers to a "VU" vector co-processor. */ int i_25_21 = (instruction >> 21) & 0x1f; @@ -3595,10 +4065,6 @@ decode_coproc (SIM_DESC sd, /* NOTREACHED */ } -#undef MY_INDEX -#undef MY_PREFIX -#undef MY_NAME - #endif /* TARGET_SKY */ /* end-sanitize-sky */ |