From 2acd126a477a02ad1674d4407ca5daad0643757a Mon Sep 17 00:00:00 2001 From: Andrew Cagney Date: Mon, 2 Feb 1998 13:49:17 +0000 Subject: [PATCH] Rewrite the mipsI/II/III pending-slot code. --- sim/mips/ChangeLog | 12 ++++ sim/mips/interp.c | 143 ++++++++++++++++++++++---------------------- sim/mips/sim-main.h | 117 +++++++++++++++++++++++++----------- 3 files changed, 163 insertions(+), 109 deletions(-) diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog index ff698cd471..a1dee76561 100644 --- a/sim/mips/ChangeLog +++ b/sim/mips/ChangeLog @@ -1,3 +1,15 @@ +Tue Feb 3 00:10:50 1998 Andrew Cagney + + * 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 * interp.c (oengine.h): Do not include when building with IGEN. diff --git a/sim/mips/interp.c b/sim/mips/interp.c index 5b2f43f8dc..095be7845f 100644 --- a/sim/mips/interp.c +++ b/sim/mips/interp.c @@ -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 <*/ diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h index fdb023c4d8..9f15093a09 100644 --- a/sim/mips/sim-main.h +++ b/sim/mips/sim-main.h @@ -285,6 +285,81 @@ GPR_(R,I) - return, as lvalue, the I'th 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 -- 2.34.1