For new IGEN simulators, rewrite checks validating correct use of the
HI/LO registers. For old gencode simulator, delete all checks.
This commit is contained in:
parent
98f5dae13b
commit
421cbaae98
5 changed files with 194 additions and 99 deletions
|
@ -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>
|
||||
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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. */
|
||||
/* 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. */
|
||||
|
||||
int hiaccess;
|
||||
int loaccess;
|
||||
#define HIACCESS ((CPU)->hiaccess)
|
||||
#define LOACCESS ((CPU)->loaccess)
|
||||
hilo_history hi_history;
|
||||
#define HIHISTORY (&(CPU)->hi_history)
|
||||
hilo_history lo_history;
|
||||
#define LOHISTORY (&(CPU)->lo_history)
|
||||
|
||||
#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
|
||||
|
||||
#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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue