mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2025-03-02 22:36:27 +00:00
Rewrite the mipsI/II/III pending-slot code.
This commit is contained in:
parent
192ae475f9
commit
2acd126a47
@ -1,3 +1,15 @@
|
||||
Tue Feb 3 00:10:50 1998 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* interp.c (ColdReset): Call PENDING_INVALIDATE.
|
||||
|
||||
* sim-main.h (ENGINE_ISSUE_PREFIX_HOOK): Call PENDING_TICK.
|
||||
|
||||
* interp.c (pending_tick): New function. Deliver pending writes.
|
||||
|
||||
* sim-main.h (PENDING_FILL, PENDING_TICK, PENDING_SCHED,
|
||||
PENDING_BIT, PENDING_INVALIDATE): Re-write pipeline code so that
|
||||
it can handle mixed sized quantites and single bits.
|
||||
|
||||
Mon Feb 2 17:43:15 1998 Andrew Cagney <cagney@b1.cygnus.com>
|
||||
|
||||
* interp.c (oengine.h): Do not include when building with IGEN.
|
||||
|
@ -1198,12 +1198,7 @@ ColdReset (SIM_DESC sd)
|
||||
|
||||
/* Ensure that any instructions with pending register updates are
|
||||
cleared: */
|
||||
{
|
||||
int loop;
|
||||
for (loop = 0; (loop < PSLOTS); loop++)
|
||||
PENDING_SLOT_REG[loop] = (LAST_EMBED_REGNUM + 1);
|
||||
PENDING_IN = PENDING_OUT = PENDING_TOTAL = 0;
|
||||
}
|
||||
PENDING_INVALIDATE();
|
||||
|
||||
/* Initialise the FPU registers to the unknown state */
|
||||
if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
|
||||
@ -3308,73 +3303,8 @@ sim_engine_run (sd, next_cpu_nr, nr_cpus, siggnal)
|
||||
CANCELDELAYSLOT();
|
||||
}
|
||||
|
||||
if (MIPSISA < 4) { /* The following is only required on pre MIPS IV processors: */
|
||||
/* Deal with pending register updates: */
|
||||
#ifdef DEBUG
|
||||
printf("DBG: EMPTY BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total);
|
||||
#endif /* DEBUG */
|
||||
if (PENDING_OUT != PENDING_IN) {
|
||||
int loop;
|
||||
int index = PENDING_OUT;
|
||||
int total = PENDING_TOTAL;
|
||||
if (PENDING_TOTAL == 0) {
|
||||
fprintf(stderr,"FATAL: Mis-match on pending update pointers\n");
|
||||
exit(1);
|
||||
}
|
||||
for (loop = 0; (loop < total); loop++) {
|
||||
#ifdef DEBUG
|
||||
printf("DBG: BEFORE index = %d, loop = %d\n",index,loop);
|
||||
#endif /* DEBUG */
|
||||
if (PENDING_SLOT_REG[index] != (LAST_EMBED_REGNUM + 1)) {
|
||||
#ifdef DEBUG
|
||||
printf("pending_slot_count[%d] = %d\n",index,PENDING_SLOT_COUNT[index]);
|
||||
#endif /* DEBUG */
|
||||
if (--(PENDING_SLOT_COUNT[index]) == 0) {
|
||||
#ifdef DEBUG
|
||||
printf("pending_slot_reg[%d] = %d\n",index,PENDING_SLOT_REG[index]);
|
||||
printf("pending_slot_value[%d] = 0x%s\n",index,pr_addr(PENDING_SLOT_VALUE[index]));
|
||||
#endif /* DEBUG */
|
||||
if (PENDING_SLOT_REG[index] == COCIDX)
|
||||
{
|
||||
if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
|
||||
{
|
||||
SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
REGISTERS[PENDING_SLOT_REG[index]] = PENDING_SLOT_VALUE[index];
|
||||
if (CURRENT_FLOATING_POINT == HARD_FLOATING_POINT)
|
||||
{
|
||||
/* The only time we have PENDING updates to FPU
|
||||
registers, is when performing binary transfers. This
|
||||
means we should update the register type field. */
|
||||
if ((PENDING_SLOT_REG[index] >= FGRIDX) && (PENDING_SLOT_REG[index] < (FGRIDX + 32)))
|
||||
FPR_STATE[PENDING_SLOT_REG[index] - FGRIDX] = fmt_uninterpreted;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("registers[%d] = 0x%s\n",PENDING_SLOT_REG[index],pr_addr(REGISTERS[PENDING_SLOT_REG[index]]));
|
||||
#endif /* DEBUG */
|
||||
PENDING_SLOT_REG[index] = (LAST_EMBED_REGNUM + 1);
|
||||
PENDING_OUT++;
|
||||
if (PENDING_OUT == PSLOTS)
|
||||
PENDING_OUT = 0;
|
||||
PENDING_TOTAL--;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("DBG: AFTER index = %d, loop = %d\n",index,loop);
|
||||
#endif /* DEBUG */
|
||||
index++;
|
||||
if (index == PSLOTS)
|
||||
index = 0;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG
|
||||
printf("DBG: EMPTY AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL);
|
||||
#endif /* DEBUG */
|
||||
}
|
||||
if (MIPSISA < 4)
|
||||
PENDING_TICK();
|
||||
|
||||
#if !defined(FASTSIM)
|
||||
if (sim_events_tickn (sd, pipeline_count))
|
||||
@ -3448,5 +3378,72 @@ pr_uword64(addr)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pending_tick (SIM_DESC sd,
|
||||
sim_cpu *cpu,
|
||||
address_word cia)
|
||||
{
|
||||
if (PENDING_TRACE)
|
||||
sim_io_printf (sd, "PENDING_DRAIN - pending_in = %d, pending_out = %d, pending_total = %d\n", PENDING_IN, PENDING_OUT, PENDING_TOTAL);
|
||||
if (PENDING_OUT != PENDING_IN)
|
||||
{
|
||||
int loop;
|
||||
int index = PENDING_OUT;
|
||||
int total = PENDING_TOTAL;
|
||||
if (PENDING_TOTAL == 0)
|
||||
sim_engine_abort (SD, CPU, cia, "PENDING_DRAIN - Mis-match on pending update pointers\n");
|
||||
for (loop = 0; (loop < total); loop++)
|
||||
{
|
||||
if (PENDING_SLOT_DEST[index] != NULL)
|
||||
{
|
||||
PENDING_SLOT_DELAY[index] -= 1;
|
||||
if (PENDING_SLOT_DELAY[index] == 0)
|
||||
{
|
||||
if (PENDING_SLOT_BIT[index] >= 0)
|
||||
switch (PENDING_SLOT_SIZE[index])
|
||||
{
|
||||
case 32:
|
||||
if (PENDING_SLOT_VALUE[index])
|
||||
*(unsigned32*)PENDING_SLOT_DEST[index] |=
|
||||
BIT32 (PENDING_SLOT_BIT[index]);
|
||||
else
|
||||
*(unsigned32*)PENDING_SLOT_DEST[index] &=
|
||||
BIT32 (PENDING_SLOT_BIT[index]);
|
||||
break;
|
||||
case 64:
|
||||
if (PENDING_SLOT_VALUE[index])
|
||||
*(unsigned64*)PENDING_SLOT_DEST[index] |=
|
||||
BIT64 (PENDING_SLOT_BIT[index]);
|
||||
else
|
||||
*(unsigned64*)PENDING_SLOT_DEST[index] &=
|
||||
BIT64 (PENDING_SLOT_BIT[index]);
|
||||
break;
|
||||
break;
|
||||
}
|
||||
else
|
||||
switch (PENDING_SLOT_SIZE[index])
|
||||
{
|
||||
case 32:
|
||||
*(unsigned32*)PENDING_SLOT_DEST[index] =
|
||||
PENDING_SLOT_VALUE[index];
|
||||
break;
|
||||
case 64:
|
||||
*(unsigned64*)PENDING_SLOT_DEST[index] =
|
||||
PENDING_SLOT_VALUE[index];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (PENDING_OUT == index)
|
||||
{
|
||||
PENDING_SLOT_DEST[index] = NULL;
|
||||
PENDING_OUT = (PENDING_OUT + 1) % PSLOTS;
|
||||
PENDING_TOTAL--;
|
||||
}
|
||||
}
|
||||
}
|
||||
index = (index + 1) % PSLOTS;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*> EOF interp.c <*/
|
||||
|
@ -285,6 +285,81 @@ GPR_<type>(R,I) - return, as lvalue, the I'th <type> of general register R
|
||||
|
||||
|
||||
|
||||
/* The following is probably not used for MIPS IV onwards: */
|
||||
/* Slots for delayed register updates. For the moment we just have a
|
||||
fixed number of slots (rather than a more generic, dynamic
|
||||
system). This keeps the simulator fast. However, we only allow
|
||||
for the register update to be delayed for a single instruction
|
||||
cycle. */
|
||||
#define PSLOTS (8) /* Maximum number of instruction cycles */
|
||||
|
||||
typedef struct _pending_write_queue {
|
||||
int in;
|
||||
int out;
|
||||
int total;
|
||||
int slot_delay[PSLOTS];
|
||||
int slot_size[PSLOTS];
|
||||
int slot_bit[PSLOTS];
|
||||
void *slot_dest[PSLOTS];
|
||||
unsigned64 slot_value[PSLOTS];
|
||||
} pending_write_queue;
|
||||
|
||||
#ifndef PENDING_TRACE
|
||||
#define PENDING_TRACE 0
|
||||
#endif
|
||||
#define PENDING_IN ((CPU)->pending.in)
|
||||
#define PENDING_OUT ((CPU)->pending.out)
|
||||
#define PENDING_TOTAL ((CPU)->pending.total)
|
||||
#define PENDING_SLOT_SIZE ((CPU)->pending.slot_size)
|
||||
#define PENDING_SLOT_BIT ((CPU)->pending.slot_size)
|
||||
#define PENDING_SLOT_DELAY ((CPU)->pending.slot_delay)
|
||||
#define PENDING_SLOT_DEST ((CPU)->pending.slot_dest)
|
||||
#define PENDING_SLOT_VALUE ((CPU)->pending.slot_value)
|
||||
|
||||
/* Invalidate the pending write queue, all pending writes are
|
||||
discarded. */
|
||||
|
||||
#define PENDING_INVALIDATE() \
|
||||
memset (&(CPU)->pending, 0, sizeof ((CPU)->pending))
|
||||
|
||||
/* Schedule a write to DEST for N cycles time. For 64 bit
|
||||
destinations, schedule two writes. For floating point registers,
|
||||
the caller should schedule a write to both the dest register and
|
||||
the FPR_STATE register. When BIT is non-negative, only BIT of DEST
|
||||
is updated. */
|
||||
|
||||
#define PENDING_SCHED(DEST,VAL,DELAY,BIT) \
|
||||
do { \
|
||||
if (PENDING_SLOT_DEST[PENDING_IN] != NULL) \
|
||||
sim_engine_abort (SD, CPU, cia, \
|
||||
"PENDING_SCHED - buffer overflow\n"); \
|
||||
if (PENDING_TRACE) \
|
||||
sim_io_printf (SD, "PENDING_SCHED - dest 0x%lx, val 0x%lx, pending_in %d, pending_out %d, pending_total %d\n", (unsigned long) (DEST), (unsigned long) (VAL), PENDING_IN, PENDING_OUT, PENDING_TOTAL); \
|
||||
PENDING_SLOT_DELAY[PENDING_IN] = (DELAY) + 1; \
|
||||
PENDING_SLOT_DEST[PENDING_IN] = &(DEST); \
|
||||
PENDING_SLOT_VALUE[PENDING_IN] = (VAL); \
|
||||
PENDING_SLOT_SIZE[PENDING_IN] = sizeof (DEST); \
|
||||
PENDING_SLOT_BIT[PENDING_IN] = (BIT); \
|
||||
} while (0)
|
||||
|
||||
#define PENDING_WRITE(DEST,VAL,DELAY) PENDING_SCHED(DEST,VAL,DELAY,-1)
|
||||
#define PENDING_BIT(DEST,VAL,DELAY,BIT) PENDING_SCHED(DEST,VAL,DELAY,BIT)
|
||||
|
||||
#define PENDING_TICK() pending_tick (SD, CPU, cia)
|
||||
|
||||
#define PENDING_FLUSH() abort () /* think about this one */
|
||||
#define PENDING_FP() abort () /* think about this one */
|
||||
|
||||
/* For backward compatibility */
|
||||
#define PENDING_FILL(R,VAL) \
|
||||
{ \
|
||||
if ((R) >= FGRIDX && (R) < FGRIDX + NR_FGR) \
|
||||
PENDING_SCHED(FGR[(R) - FGRIDX], VAL, 2, -1); \
|
||||
else \
|
||||
PENDING_SCHED(GPR[(R)], VAL, 2, -1); \
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct _sim_cpu {
|
||||
|
||||
@ -337,6 +412,8 @@ struct _sim_cpu {
|
||||
|
||||
#define ENGINE_ISSUE_PREFIX_HOOK() \
|
||||
{ \
|
||||
/* Perform any pending writes */ \
|
||||
PENDING_TICK(); \
|
||||
/* Set previous flag, depending on current: */ \
|
||||
if (STATE & simPCOC0) \
|
||||
STATE |= simPCOC1; \
|
||||
@ -376,6 +453,7 @@ struct _sim_cpu {
|
||||
|
||||
#define GPR (®ISTERS[0])
|
||||
#define GPR_SET(N,VAL) (REGISTERS[(N)] = (VAL))
|
||||
#define NR_FGR (32)
|
||||
#define FGRIDX (38)
|
||||
#define FGR (®ISTERS[FGRIDX])
|
||||
#define LO (REGISTERS[33])
|
||||
@ -412,42 +490,7 @@ struct _sim_cpu {
|
||||
FP_formats fpr_state[32];
|
||||
#define FPR_STATE ((CPU)->fpr_state)
|
||||
|
||||
|
||||
/* Slots for delayed register updates. For the moment we just have a
|
||||
fixed number of slots (rather than a more generic, dynamic
|
||||
system). This keeps the simulator fast. However, we only allow
|
||||
for the register update to be delayed for a single instruction
|
||||
cycle. */
|
||||
#define PSLOTS (5) /* Maximum number of instruction cycles */
|
||||
int pending_in;
|
||||
int pending_out;
|
||||
int pending_total;
|
||||
int pending_slot_count[PSLOTS];
|
||||
int pending_slot_reg[PSLOTS];
|
||||
unsigned_word pending_slot_value[PSLOTS];
|
||||
#define PENDING_IN ((CPU)->pending_in)
|
||||
#define PENDING_OUT ((CPU)->pending_out)
|
||||
#define PENDING_TOTAL ((CPU)->pending_total)
|
||||
#define PENDING_SLOT_COUNT ((CPU)->pending_slot_count)
|
||||
#define PENDING_SLOT_REG ((CPU)->pending_slot_reg)
|
||||
#define PENDING_SLOT_VALUE ((CPU)->pending_slot_value)
|
||||
|
||||
/* The following are not used for MIPS IV onwards: */
|
||||
#define PENDING_FILL(r,v) {\
|
||||
/* printf("DBG: FILL BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL); */\
|
||||
if (PENDING_SLOT_REG[PENDING_IN] != (LAST_EMBED_REGNUM + 1))\
|
||||
sim_io_eprintf(sd,"Attempt to over-write pending value\n");\
|
||||
PENDING_SLOT_COUNT[PENDING_IN] = 2;\
|
||||
PENDING_SLOT_REG[PENDING_IN] = (r);\
|
||||
PENDING_SLOT_VALUE[PENDING_IN] = (uword64)(v);\
|
||||
/*printf("DBG: FILL reg %d value = 0x%s\n",(r),pr_addr(v));*/\
|
||||
PENDING_TOTAL++;\
|
||||
PENDING_IN++;\
|
||||
if (PENDING_IN == PSLOTS)\
|
||||
PENDING_IN = 0;\
|
||||
/*printf("DBG: FILL AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL);*/\
|
||||
}
|
||||
|
||||
pending_write_queue pending;
|
||||
|
||||
/* LLBIT = Load-Linked bit. A bit of "virtual" state used by atomic
|
||||
read-write instructions. It is set when a linked load occurs. It
|
||||
@ -737,4 +780,6 @@ unsigned32 ifetch32 PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, addres
|
||||
void dotrace PARAMS ((SIM_DESC sd, sim_cpu *cpu, FILE *tracefh, int type, SIM_ADDR address, int width, char *comment, ...));
|
||||
FILE *tracefh;
|
||||
|
||||
void pending_tick PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia));
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user