HI/LO registers. For old gencode simulator, delete all checks.
+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>
{
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");
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) {
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");
/* 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");
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 */
{
/* 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));
#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
+// 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:
//
: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];
: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];
: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];
: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];
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)
: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
: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
*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
}
*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
}
: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));
: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));
// start-sanitize-vr5400
*vr5400:
// end-sanitize-vr5400
-// start-sanitize-r5900
-*r5900:
-// end-sanitize-r5900
*r3900:
// start-sanitize-tx19
*tx19:
+/* 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"
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.
/* 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;
#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;