diff options
-rw-r--r-- | sim/mips/ChangeLog | 48 | ||||
-rw-r--r-- | sim/mips/gencode.c | 15 | ||||
-rw-r--r-- | sim/mips/interp.c | 22 | ||||
-rw-r--r-- | sim/mips/mips.igen | 126 | ||||
-rw-r--r-- | sim/mips/sim-main.h | 84 |
5 files changed, 195 insertions, 100 deletions
diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog index 8bc443c..f1725ab 100644 --- a/sim/mips/ChangeLog +++ b/sim/mips/ChangeLog @@ -1,3 +1,51 @@ +Mon Apr 20 11:26:55 1998 Andrew Cagney <cagney@b1.cygnus.com> + + * sim-main.h (struct hilo_access, struct hilo_history): Define, + contains HI/LO access history. + (struct _sim_cpu): Make hiaccess and loaccess of type hilo_access. + (HIACCESS, LOACCESS): Delete, replace with + (HIHISTORY, LOHISTORY): New macros. + (start-sanitize-r5900): + (struct sim_5900_cpu): Make hi1access, lo1access of type + hilo_access. + (HI1ACCESS, LO1ACCESS): Delete, replace with + (HI1HISTORY, LO1HISTORY): New macros. + (end-sanitize-r5900): + (CHECKHILO): Delete all, moved to mips.igen + + * gencode.c (build_instruction): Do not generate checks for + correct HI/LO register usage. + + * interp.c (old_engine_run): Delete checks for correct HI/LO + register usage. + + * mips.igen (check_mt_hilo, check_mf_hilo, check_op_hilo, + check_mf_cycles): New functions. + (do_mfhi, do_mflo, "mthi", "mtlo", do_ddiv, do_ddivu, do_div, + do_divu, domultx, do_mult, do_multu): Use. + + * tx.igen ("madd", "maddu"): Use. + (start-sanitize-r5900): + + r5900.igen: Update all HI/LO checks. + ("mfhi1", "mflo1", "mthi1", "mthi1", "pmfhi", "pmflo", "pmfhl", + "pmthi", "pmtlo", "mpthl"): Check MF/MT HI/LO. + ("mult1", "div1", "divu1", "multu1", "madd1", "maddu1", "pdivbw", + "pdivuw", "pdivw", "phmaddh", "phmsubh", "pmaddh", "madduw", + "pmaddw", "pmsubh", "pmsubw", "pmulth", "pmultuw", "pmultw"): + Check HI/LO op. + (end-sanitize-r5900): + +start-sanitize-sky +Mon Apr 20 18:39:47 1998 Frank Ch. Eigler <fche@cygnus.com> + + * interp.c (decode_coproc): Correct CMFC2/QMTC2 + GPR access. + + * r5900.igen (LQ,SQ): Use a pair of 64-bit accesses + instead of a single 128-bit access. + +end-sanitize-sky start-sanitize-sky Fri Apr 17 14:50:39 1998 Frank Ch. Eigler <fche@cygnus.com> diff --git a/sim/mips/gencode.c b/sim/mips/gencode.c index 44fac70..becc194 100644 --- a/sim/mips/gencode.c +++ b/sim/mips/gencode.c @@ -2527,9 +2527,6 @@ build_instruction (doisa, features, mips16, insn) { char* pipe = (insn->flags & PIPE1) ? "1" : ""; - if (features & FEATURE_WARN_LOHI) { - printf(" CHECKHILO(\"Multiplication\");\n"); - } printf(" {\n"); if (GETDATASIZEINSN(insn) == DOUBLEWORD) { printf(" uword64 mid;\n"); @@ -2578,9 +2575,6 @@ build_instruction (doisa, features, mips16, insn) int boolU = (insn->flags & UNSIGNED); char* pipe = (insn->flags & PIPE1) ? "1" : ""; - if (features & FEATURE_WARN_LOHI) { - printf(" CHECKHILO(\"Division\");\n"); - } printf(" {\n"); if (GETDATASIZEINSN(insn) == DOUBLEWORD) { @@ -2697,14 +2691,8 @@ build_instruction (doisa, features, mips16, insn) if (insn->flags & LEFT) printf(" GPR[destreg] = %s%s;\n",regname,(pipe1 ? "1" : "")); else { - if (features & FEATURE_WARN_LOHI) { - printf(" if (%s%sACCESS != 0)\n",regname,(pipe1 ? "1" : "")); - printf(" sim_io_eprintf(sd,\"MT (move-to) over-writing %s register value\\n\");\n",regname); - } printf(" %s%s = op1;\n",regname,(pipe1 ? "1" : "")); } - if (features & FEATURE_WARN_LOHI) - printf(" %s%sACCESS = 3; /* 3rd instruction will be safe */\n",regname,(pipe1 ? "1" : "")); } else if (insn->flags & SHIFT16) printf(" GPR[destreg] = (op2 << 16);\n"); @@ -2813,9 +2801,6 @@ build_instruction (doisa, features, mips16, insn) /* Some of this code is shared with the standard multiply routines, so an effort should be made to merge where possible. */ - if (features & FEATURE_WARN_LOHI) { - printf(" CHECKHILO(\"Multiply-Add\");\n"); - } if (features & FEATURE_WARN_RESULT) { /* Give user a warning if either op1 or op2 are not 16bit signed integers */ printf(" if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n"); diff --git a/sim/mips/interp.c b/sim/mips/interp.c index 8f45da9..612b73b 100644 --- a/sim/mips/interp.c +++ b/sim/mips/interp.c @@ -3300,8 +3300,8 @@ decode_coproc (SIM_DESC sd, read_vu_vec_reg(&(vu0_device.regs), id, 1, A4_16(& xyzw, 2)); read_vu_vec_reg(&(vu0_device.regs), id, 2, A4_16(& xyzw, 1)); read_vu_vec_reg(&(vu0_device.regs), id, 3, A4_16(& xyzw, 0)); - xyzw = T2H_16(xyzw); - memcpy(& GPR[rt], & xyzw, sizeof(xyzw)); + GPR[rt] = T2H_8(* A8_16(& xyzw, 1)); + GPR1[rt] = T2H_8(* A8_16(& xyzw, 0)); } else /* CFC2 */ { @@ -3334,8 +3334,8 @@ decode_coproc (SIM_DESC sd, /* perform VU register address */ if(i_25_21 == 0x05) /* QMTC2 */ { - unsigned_16 xyzw; - memcpy(& xyzw, & GPR[rt], sizeof(xyzw)); + unsigned_16 xyzw = U16_8(GPR1[rt], GPR[rt]); + xyzw = H2T_16(xyzw); /* one word at a time, argh! */ write_vu_vec_reg(&(vu0_device.regs), id, 0, A4_16(& xyzw, 3)); @@ -3624,20 +3624,6 @@ sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal) #error "Mismatch between configure WITH_FLOATING_POINT and gencode HASFPU" #endif -#if defined(WARN_LOHI) - /* Decrement the HI/LO validity ticks */ - if (HIACCESS > 0) - HIACCESS--; - if (LOACCESS > 0) - LOACCESS--; - /* start-sanitize-r5900 */ - if (HI1ACCESS > 0) - HI1ACCESS--; - if (LO1ACCESS > 0) - LO1ACCESS--; - /* end-sanitize-r5900 */ -#endif /* WARN_LOHI */ - /* For certain MIPS architectures, GPR[0] is hardwired to zero. We should check for it being changed. It is better doing it here, than within the simulator, since it will help keep the simulator diff --git a/sim/mips/mips.igen b/sim/mips/mips.igen index 7b4102c..89c1986 100644 --- a/sim/mips/mips.igen +++ b/sim/mips/mips.igen @@ -98,6 +98,91 @@ +// Helper: +// +// Check that an access to a HI/LO register meets timing requirements +// +// The following requirements exist: +// +// - A MT {HI,LO} update was not immediatly preceeded by a MF {HI,LO} read +// - A OP {HI,LO} update was not immediatly preceeded by a MF {HI,LO} read +// - A MF {HI,LO} read was not corrupted by a preceeding MT{LO,HI} update +// corruption occures when MT{LO,HI} is preceeded by a OP {HI,LO}. +// + +:function:::int:check_mf_cycles:hilo_history *history, signed64 time, const char *new +{ + if (history->mf.timestamp + 3 > time) + { + sim_engine_abort (SD, CPU, CIA, "HILO: %s: %s at 0x%08lx too close to MF at 0x%08lx\n", + itable[MY_INDEX].name, + new, (long) CIA, + (long) history->mf.cia); + return 0; + } + return 1; +} + +:function:::int:check_mt_hilo:hilo_history *history +{ + signed64 time = sim_events_time (SD); + int ok = check_mf_cycles (SD_, history, time, "MT"); + history->mt.timestamp = time; + history->mt.cia = CIA; + return ok; +} + +:function:::int:check_mf_hilo:hilo_history *history, hilo_history *peer +{ + signed64 time = sim_events_time (SD); + int ok = 1; + if (peer != NULL + && peer->mt.timestamp > history->op.timestamp + && history->mf.timestamp < history->op.timestamp) + { + /* The peer has been written to since the last OP yet we have + not */ + sim_engine_abort (SD, CPU, CIA, "HILO: %s: MF at 0x%08lx following OP at 0x%08lx corrupted by MT at 0x%08lx\n", + itable[MY_INDEX].name, + (long) CIA, + (long) history->op.cia, + (long) peer->mt.cia); + ok = 0; + } + history->mf.timestamp = time; + history->mf.cia = CIA; + return ok; +} + +:function:::int:check_op_hilo:hilo_history *hi, hilo_history *lo +*mipsI,mipsII,mipsIII,mipsIV: +*vr5000: +// start-sanitize-vr4320 +*vr4320: +// end-sanitize-vr4320 +// start-sanitize-vr5400 +*vr5400: +// end-sanitize-vr5400 +*r3900: +// start-sanitize-tx19 +*tx19: +// end-sanitize-tx19 +// start-sanitize-r5900 +*r5900: +// end-sanitize-r5900 +{ + signed64 time = sim_events_time (SD); + int ok = (check_mf_cycles (SD_, hi, time, "OP") + && check_mf_cycles (SD_, lo, time, "OP")); + hi->op.timestamp = time; + lo->op.timestamp = time; + hi->op.cia = CIA; + lo->op.cia = CIA; + return ok; +} + + + // // Mips Architecture: // @@ -867,8 +952,8 @@ :function:64::void:do_ddiv:int rs, int rt { + check_op_hilo (SD_, HIHISTORY, LOHISTORY); TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); - CHECKHILO ("Division"); { signed64 n = GPR[rs]; signed64 d = GPR[rt]; @@ -916,8 +1001,8 @@ :function:64::void:do_ddivu:int rs, int rt { + check_op_hilo (SD_, HIHISTORY, LOHISTORY); TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); - CHECKHILO ("Division"); { unsigned64 n = GPR[rs]; unsigned64 d = GPR[rt]; @@ -957,8 +1042,8 @@ :function:::void:do_div:int rs, int rt { + check_op_hilo (SD_, HIHISTORY, LOHISTORY); TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); - CHECKHILO("Division"); { signed32 n = GPR[rs]; signed32 d = GPR[rt]; @@ -1006,8 +1091,8 @@ :function:::void:do_divu:int rs, int rt { + check_op_hilo (SD_, HIHISTORY, LOHISTORY); TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); - CHECKHILO ("Division"); { unsigned32 n = GPR[rs]; unsigned32 d = GPR[rt]; @@ -1060,8 +1145,8 @@ int sign; unsigned64 op1 = GPR[rs]; unsigned64 op2 = GPR[rt]; + check_op_hilo (SD_, HIHISTORY, LOHISTORY); TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); - CHECKHILO ("Multiplication"); /* make signed multiply unsigned */ sign = 0; if (signed_p) @@ -2032,12 +2117,10 @@ :function:::void:do_mfhi:int rd { + check_mf_hilo (SD_, HIHISTORY, LOHISTORY); TRACE_ALU_INPUT1 (HI); GPR[rd] = HI; TRACE_ALU_RESULT (GPR[rd]); -#if 0 - HIACCESS = 3; -#endif } 000000,0000000000,5.RD,00000,010000:SPECIAL:32::MFHI @@ -2065,12 +2148,10 @@ :function:::void:do_mflo:int rd { + check_mf_hilo (SD_, LOHISTORY, HIHISTORY); TRACE_ALU_INPUT1 (LO); GPR[rd] = LO; TRACE_ALU_RESULT (GPR[rd]); -#if 0 - LOACCESS = 3; /* 3rd instruction will be safe */ -#endif } 000000,0000000000,5.RD,00000,010010:SPECIAL:32::MFLO @@ -2154,14 +2235,8 @@ *tx19: // end-sanitize-tx19 { -#if 0 - if (HIACCESS != 0) - sim_io_eprintf (sd, "MT (move-to) over-writing HI register value\n"); -#endif + check_mt_hilo (SD_, HIHISTORY); HI = GPR[RS]; -#if 0 - HIACCESS = 3; /* 3rd instruction will be safe */ -#endif } @@ -2184,14 +2259,8 @@ *tx19: // end-sanitize-tx19 { -#if 0 - if (LOACCESS != 0) - sim_io_eprintf (sd, "MT (move-to) over-writing LO register value\n"); -#endif + check_mt_hilo (SD_, LOHISTORY); LO = GPR[RS]; -#if 0 - LOACCESS = 3; /* 3rd instruction will be safe */ -#endif } @@ -2199,8 +2268,8 @@ :function:::void:do_mult:int rs, int rt, int rd { signed64 prod; + check_op_hilo (SD_, HIHISTORY, LOHISTORY); TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); - CHECKHILO ("Multiplication"); prod = (((signed64)(signed32) GPR[rs]) * ((signed64)(signed32) GPR[rt])); LO = EXTEND32 (VL4_8 (prod)); @@ -2242,8 +2311,8 @@ :function:::void:do_multu:int rs, int rt, int rd { unsigned64 prod; + check_op_hilo (SD_, HIHISTORY, LOHISTORY); TRACE_ALU_INPUT2 (GPR[rs], GPR[rt]); - CHECKHILO ("Multiplication"); prod = (((unsigned64)(unsigned32) GPR[rs]) * ((unsigned64)(unsigned32) GPR[rt])); LO = EXTEND32 (VL4_8 (prod)); @@ -3883,9 +3952,6 @@ // start-sanitize-vr5400 *vr5400: // end-sanitize-vr5400 -// start-sanitize-r5900 -*r5900: -// end-sanitize-r5900 *r3900: // start-sanitize-tx19 *tx19: diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h index 594a9f7..9a8cd15 100644 --- a/sim/mips/sim-main.h +++ b/sim/mips/sim-main.h @@ -170,6 +170,30 @@ convert (SD, CPU, cia, rm, op, from, to) +/* HI/LO register accesses */ + +/* For some MIPS targets, the HI/LO registers have certain timing + restrictions in that, for instance, a read of a HI register must be + separated by at least three instructions from a preceeding read. + + The struct below is used to record the last access by each of A MT, + MF or other OP instruction to a HI/LO register. See mips.igen for + more details. */ + +typedef struct _hilo_access { + signed64 timestamp; + address_word cia; +} hilo_access; + +typedef struct _hilo_history { + hilo_access mt; + hilo_access mf; + hilo_access op; +} hilo_history; + + + + /* Integer ALU operations: */ #include "sim-alu.h" @@ -204,6 +228,17 @@ enum { R5900_FCSR_SU = BIT (3), }; +/* Table 10-1 FP format values. + Note: some of these bits are different to what is found in a + standard MIPS manual. */ +enum { + R5900_EXPMAX = 128, + R5900_EXPMIN = -127, + R5900_EXPBIAS = 127, +}; + + + typedef struct _sim_r5900_cpu { /* The R5900 has 32 x 128bit general purpose registers. @@ -237,16 +272,10 @@ typedef struct _sim_r5900_cpu { /* See comments below about needing to count cycles between updating and setting HI/LO registers */ - int hi1access; - int lo1access; -#define HI1ACCESS ((CPU)->r5900.hi1access) -#define LO1ACCESS ((CPU)->r5900.lo1access) -#if 0 -#define CHECKHILO(s) {\ - if ((HIACCESS != 0) || (LOACCESS != 0) || (HI1ACCESS != 0) || (LO1ACCESS != 0))\ - sim_io_eprintf(sd,"%s over-writing HI and LO registers values (PC = 0x%s HLPC = 0x%s)\n",(s),pr_addr(PC),pr_addr(HLPC));\ -} -#endif + hilo_history hi1_history; +#define HI1HISTORY (&(CPU)->r5900.hi1_history) + hilo_history lo1_history; +#define LO1HISTORY (&(CPU)->r5900.lo1_history) } sim_r5900_cpu; @@ -601,34 +630,15 @@ struct _sim_cpu { #define LLBIT ((CPU)->llbit) -/* The HIACCESS and LOACCESS counts are used to ensure that - corruptions caused by using the HI or LO register to close to a - following operation are spotted. */ - - int hiaccess; - int loaccess; -#define HIACCESS ((CPU)->hiaccess) -#define LOACCESS ((CPU)->loaccess) - -#if 0 - unsigned_word HLPC; - /* If either of the preceding two instructions have accessed the HI - or LO registers, then the values they see should be - undefined. However, to keep the simulator world simple, we just - let them use the value read and raise a warning to notify the - user: */ -#define CHECKHILO(s) {\ - if ((HIACCESS != 0) || (LOACCESS != 0)) \ - sim_io_eprintf(sd,"%s over-writing HI and LO registers values (PC = 0x%s HLPC = 0x%s)\n",(s),pr_addr(PC),pr_addr(HLPC));\ -} -#endif +/* The HIHISTORY and LOHISTORY timestamps are used to ensure that + corruptions caused by using the HI or LO register too close to a + following operation is spotted. See mips.igen for more details. */ + + hilo_history hi_history; +#define HIHISTORY (&(CPU)->hi_history) + hilo_history lo_history; +#define LOHISTORY (&(CPU)->lo_history) -#if !defined CHECKHILO - /* The 4300 and a few other processors have interlocks on hi/lo - register reads, and hence do not have this problem. To avoid - spurious warnings, we just disable this always. */ -#define CHECKHILO(s) -#endif /* start-sanitize-r5900 */ sim_r5900_cpu r5900; |