diff options
Diffstat (limited to 'sim/mips')
-rw-r--r-- | sim/mips/ChangeLog | 17 | ||||
-rw-r--r-- | sim/mips/cp1.c | 4 | ||||
-rw-r--r-- | sim/mips/interp.c | 43 | ||||
-rw-r--r-- | sim/mips/mips.igen | 110 | ||||
-rw-r--r-- | sim/mips/sim-main.h | 5 |
5 files changed, 153 insertions, 26 deletions
diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog index bdfd8a8..8f505c4 100644 --- a/sim/mips/ChangeLog +++ b/sim/mips/ChangeLog @@ -1,3 +1,20 @@ +2002-05-01 Chris Demetriou <cgd@broadcom.com> + + * cp1.c (store_fpr): Remove #ifdef'd out call to UndefinedResult + which wouldn't compile anyway. + * sim-main.h (unpredictable_action): New function prototype. + (Unpredictable): Define to call igen function unpredictable(). + (NotWordValue): New macro to call igen function not_word_value(). + (UndefinedResult): Remove. + * interp.c (undefined_result): Remove. + (unpredictable_action): New function. + * mips.igen (not_word_value, unpredictable): New functions. + (ADD, ADDI, do_addiu, do_addu, BGEZAL, BGEZALL, BLTZAL, BLTZALL) + (CLO, CLZ, MADD, MADDU, MSUB, MSUBU, MUL, do_mult, do_multu) + (do_sra, do_srav, do_srl, do_srlv, SUB, do_subu): Invoke + NotWordValue() to check for unpredictable inputs, then + Unpredictable() to handle them. + 2002-02-24 Chris Demetriou <cgd@broadcom.com> * mips.igen: Fix formatting of calls to Unpredictable(). diff --git a/sim/mips/cp1.c b/sim/mips/cp1.c index 9bd08f9..063c241 100644 --- a/sim/mips/cp1.c +++ b/sim/mips/cp1.c @@ -279,10 +279,6 @@ store_fpr (SIM_DESC sd, break; } } -#if defined(WARN_RESULT) - else - UndefinedResult (); -#endif /* WARN_RESULT */ if (err) SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR ()"); diff --git a/sim/mips/interp.c b/sim/mips/interp.c index 5bd61a8..0c587e0 100644 --- a/sim/mips/interp.c +++ b/sim/mips/interp.c @@ -1869,28 +1869,31 @@ signal_exception (SIM_DESC sd, -#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 - undefined. However, this should not affect the instruction - stream. All that is meant to happen is that the destination - register is set to an undefined result. To keep the simulator - simple, we just don't bother updating the destination register, so - the overall result will be undefined. If desired we can stop the - simulator by raising a pseudo-exception. */ -#define UndefinedResult() undefined_result (sd,cia) -static void -undefined_result(sd,cia) - SIM_DESC sd; - address_word cia; +/* This function implements what the MIPS32 and MIPS64 ISAs define as + "UNPREDICTABLE" behaviour. + + About UNPREDICTABLE behaviour they say: "UNPREDICTABLE results + may vary from processor implementation to processor implementation, + instruction to instruction, or as a function of time on the same + implementation or instruction. Software can never depend on results + that are UNPREDICTABLE. ..." (MIPS64 Architecture for Programmers + Volume II, The MIPS64 Instruction Set. MIPS Document MD00087 revision + 0.95, page 2.) + + For UNPREDICTABLE behaviour, we print a message, if possible print + the offending instructions mips.igen instruction name (provided by + the caller), and stop the simulator. + + XXX FIXME: eventually, stopping the simulator should be made conditional + on a command-line option. */ +void +unpredictable_action(sim_cpu *cpu, address_word cia) { - sim_io_eprintf(sd,"UndefinedResult: PC = 0x%s\n",pr_addr(cia)); -#if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */ - state |= simSTOP; -#endif - return; + 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); } -#endif /* WARN_RESULT */ /*-- co-processor support routines ------------------------------------------*/ diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen index 7cb9d10..cd96766 100644 --- a/sim/mips/mips.igen +++ b/sim/mips/mips.igen @@ -144,6 +144,70 @@ // Helper: // +// Check that a 32-bit register value is properly sign-extended. +// (See NotWordValue in ISA spec.) +// + +:function:::int:not_word_value:unsigned_word value +*mipsI: +*mipsII: +*mipsIII: +*mipsIV: +*mipsV: +*vr4100: +*vr5000: +*r3900: +{ + /* For historical simulator compatibility (until documentation is + found that makes these operations unpredictable on some of these + architectures), this check never returns true. */ + return 0; +} + +:function:::int:not_word_value:unsigned_word value +*mips32: +{ + /* On MIPS32, since registers are 32-bits, there's no check to be done. */ + return 0; +} + +:function:::int:not_word_value:unsigned_word value +*mips64: +{ + return ((value >> 32) != (value & 0x80000000 ? 0xFFFFFFFF : 0)); +} + + +// Helper: +// +// Handle UNPREDICTABLE operation behaviour. The goal here is to prevent +// theoretically portable code which invokes non-portable behaviour from +// running with no indication of the portability issue. +// (See definition of UNPREDICTABLE in ISA spec.) +// + +:function:::void:unpredictable: +*mipsI: +*mipsII: +*mipsIII: +*mipsIV: +*mipsV: +*vr4100: +*vr5000: +*r3900: +{ +} + +:function:::void:unpredictable: +*mips32: +*mips64: +{ + unpredictable_action (CPU, CIA); +} + + +// Helper: +// // Check that an access to a HI/LO register meets timing requirements // // The following requirements exist: @@ -340,6 +404,8 @@ *vr5000: *r3900: { + if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); { ALU32_BEGIN (GPR[RS]); @@ -364,6 +430,8 @@ *vr5000: *r3900: { + if (NotWordValue (GPR[RS])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[RS], EXTEND16 (IMMEDIATE)); { ALU32_BEGIN (GPR[RS]); @@ -377,6 +445,8 @@ :function:::void:do_addiu:int rs, int rt, unsigned16 immediate { + if (NotWordValue (GPR[rs])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[rs], EXTEND16 (immediate)); GPR[rt] = EXTEND32 (GPR[rs] + EXTEND16 (immediate)); TRACE_ALU_RESULT (GPR[rt]); @@ -402,6 +472,8 @@ :function:::void:do_addu:int rs, int rt, int rd { + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); GPR[rd] = EXTEND32 (GPR[rs] + GPR[rt]); TRACE_ALU_RESULT (GPR[rd]); @@ -558,6 +630,8 @@ { address_word offset = EXTEND16 (OFFSET) << 2; check_branch_bug (); + if (RS == 31) + Unpredictable (); RA = (CIA + 8); if ((signed_word) GPR[RS] >= 0) { @@ -582,6 +656,8 @@ { address_word offset = EXTEND16 (OFFSET) << 2; check_branch_bug (); + if (RS == 31) + Unpredictable (); RA = (CIA + 8); /* NOTE: The branch occurs AFTER the next instruction has been executed */ @@ -762,6 +838,8 @@ { address_word offset = EXTEND16 (OFFSET) << 2; check_branch_bug (); + if (RS == 31) + Unpredictable (); RA = (CIA + 8); /* NOTE: The branch occurs AFTER the next instruction has been executed */ @@ -788,6 +866,8 @@ { address_word offset = EXTEND16 (OFFSET) << 2; check_branch_bug (); + if (RS == 31) + Unpredictable (); RA = (CIA + 8); if ((signed_word) GPR[RS] < 0) { @@ -926,6 +1006,8 @@ unsigned32 i, mask; if (RT != RD) Unpredictable (); + if (NotWordValue (GPR[RS])) + Unpredictable (); TRACE_ALU_INPUT1 (GPR[RS]); for (mask = ((unsigned32)1<<31), i = 0; i < 32; ++i) { @@ -948,6 +1030,8 @@ unsigned32 i, mask; if (RT != RD) Unpredictable (); + if (NotWordValue (GPR[RS])) + Unpredictable (); TRACE_ALU_INPUT1 (GPR[RS]); for (mask = ((unsigned32)1<<31), i = 0; i < 32; ++i) { @@ -2099,6 +2183,8 @@ { signed64 temp; check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); temp = (U8_4 (VL4_8 (HI), VL4_8 (LO)) + ((signed64) EXTEND32 (GPR[RT]) * (signed64) EXTEND32 (GPR[RS]))); @@ -2116,6 +2202,8 @@ { unsigned64 temp; check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); temp = (U8_4 (VL4_8 (HI), VL4_8 (LO)) + ((unsigned64) VL4_8 (GPR[RS]) * (unsigned64) VL4_8 (GPR[RT]))); @@ -2212,6 +2300,8 @@ { signed64 temp; check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); temp = (U8_4 (VL4_8 (HI), VL4_8 (LO)) - ((signed64) EXTEND32 (GPR[RT]) * (signed64) EXTEND32 (GPR[RS]))); @@ -2229,6 +2319,8 @@ { unsigned64 temp; check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); temp = (U8_4 (VL4_8 (HI), VL4_8 (LO)) - ((unsigned64) VL4_8 (GPR[RS]) * (unsigned64) VL4_8 (GPR[RT]))); @@ -2283,6 +2375,8 @@ *mips64: { signed64 prod; + if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); prod = (((signed64)(signed32) GPR[RS]) * ((signed64)(signed32) GPR[RT])); @@ -2296,6 +2390,8 @@ { signed64 prod; check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); prod = (((signed64)(signed32) GPR[rs]) * ((signed64)(signed32) GPR[rt])); @@ -2335,6 +2431,8 @@ { unsigned64 prod; check_mult_hilo (SD_, HIHISTORY, LOHISTORY); + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); prod = (((unsigned64)(unsigned32) GPR[rs]) * ((unsigned64)(unsigned32) GPR[rt])); @@ -2893,6 +2991,8 @@ :function:::void:do_sra:int rt, int rd, int shift { signed32 temp = (signed32) GPR[rt] >> shift; + if (NotWordValue (GPR[rt])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[rt], shift); GPR[rd] = EXTEND32 (temp); TRACE_ALU_RESULT (GPR[rd]); @@ -2920,6 +3020,8 @@ { int s = MASKED (GPR[rs], 4, 0); signed32 temp = (signed32) GPR[rt] >> s; + if (NotWordValue (GPR[rt])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[rt], s); GPR[rd] = EXTEND32 (temp); TRACE_ALU_RESULT (GPR[rd]); @@ -2946,6 +3048,8 @@ :function:::void:do_srl:int rt, int rd, int shift { unsigned32 temp = (unsigned32) GPR[rt] >> shift; + if (NotWordValue (GPR[rt])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[rt], shift); GPR[rd] = EXTEND32 (temp); TRACE_ALU_RESULT (GPR[rd]); @@ -2972,6 +3076,8 @@ { int s = MASKED (GPR[rs], 4, 0); unsigned32 temp = (unsigned32) GPR[rt] >> s; + if (NotWordValue (GPR[rt])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[rt], s); GPR[rd] = EXTEND32 (temp); TRACE_ALU_RESULT (GPR[rd]); @@ -3007,6 +3113,8 @@ *vr5000: *r3900: { + if (NotWordValue (GPR[RS]) || NotWordValue (GPR[RT])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[RS], GPR[RT]); { ALU32_BEGIN (GPR[RS]); @@ -3019,6 +3127,8 @@ :function:::void:do_subu:int rs, int rt, int rd { + if (NotWordValue (GPR[rs]) || NotWordValue (GPR[rt])) + Unpredictable (); TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); GPR[rd] = EXTEND32 (GPR[rs] - GPR[rt]); TRACE_ALU_RESULT (GPR[rd]); diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h index 7c34888..4373c00 100644 --- a/sim/mips/sim-main.h +++ b/sim/mips/sim-main.h @@ -771,8 +771,9 @@ INLINE_SIM_MAIN (void) prefetch PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word #define Prefetch(CCA,pAddr,vAddr,DATA,hint) \ prefetch (SD, CPU, cia, CCA, pAddr, vAddr, DATA, hint) -#define UndefinedResult() -#define Unpredictable() +void unpredictable_action (sim_cpu *cpu, address_word cia); +#define NotWordValue(val) not_word_value (SD_, (val)) +#define Unpredictable() unpredictable (SD_) INLINE_SIM_MAIN (unsigned32) ifetch32 PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, address_word vaddr)); #define IMEM32(CIA) ifetch32 (SD, CPU, (CIA), (CIA)) |