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:
Andrew Cagney 1998-04-21 01:17:58 +00:00
parent 98f5dae13b
commit 421cbaae98
5 changed files with 194 additions and 99 deletions

View file

@ -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>

View file

@ -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");

View file

@ -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

View file

@ -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:

View file

@ -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;