diff options
author | Andrew Cagney <cagney@redhat.com> | 1997-10-14 09:26:03 +0000 |
---|---|---|
committer | Andrew Cagney <cagney@redhat.com> | 1997-10-14 09:26:03 +0000 |
commit | 0c2c5f614114718e53d7c3dc03f6c5c86c48cf30 (patch) | |
tree | ef9d7ea4aa1a1bd0fafa224a89504e6953a6ef27 /sim | |
parent | 1b217de0f356cc7280b54d37a17c4020b892566d (diff) | |
download | gdb-0c2c5f614114718e53d7c3dc03f6c5c86c48cf30.zip gdb-0c2c5f614114718e53d7c3dc03f6c5c86c48cf30.tar.gz gdb-0c2c5f614114718e53d7c3dc03f6c5c86c48cf30.tar.bz2 |
Move global MIPS simulator variables into sim_cpu struct.
Diffstat (limited to 'sim')
-rw-r--r-- | sim/mips/ChangeLog | 18 | ||||
-rw-r--r-- | sim/mips/Makefile.in | 2 | ||||
-rw-r--r-- | sim/mips/interp.c | 433 | ||||
-rw-r--r-- | sim/mips/sim-main.h | 246 |
4 files changed, 369 insertions, 330 deletions
diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog index 0a032c8..0e51af9 100644 --- a/sim/mips/ChangeLog +++ b/sim/mips/ChangeLog @@ -1,3 +1,21 @@ +Tue Oct 14 17:38:18 1997 Andrew Cagney <cagney@b1.cygnus.com> + + * Makefile.in (interp.o): Depends on sim-main.h + + * interp.c (mips16_entry, ColdReset,dotrace): Add SD argument. Use GPR not registers. + + * sim-main.h (sim_cpu): Add registers, register_widths, fpr_state, + ipc, dspc, pending_*, hiaccess, loaccess, state, dsstate fields. + (REGISTERS, REGISTER_WIDTHS, FPR_STATE, IPC, DSPC, PENDING_*, + STATE, DSSTATE): Define + (GPR, FGRIDX, ..): Define. + + * interp.c (registers, register_widths, fpr_state, ipc, dspc, + pending_*, hiaccess, loaccess, state, dsstate): Delete globals. + (GPR, FGRIDX, ...): Delete macros. + + * interp.c: Update names to match defines from sim-main.h + Tue Oct 14 15:11:45 1997 Andrew Cagney <cagney@b1.cygnus.com> * interp.c (sim_monitor): Add SD argument. diff --git a/sim/mips/Makefile.in b/sim/mips/Makefile.in index 445b995..d82194f 100644 --- a/sim/mips/Makefile.in +++ b/sim/mips/Makefile.in @@ -44,7 +44,7 @@ SIM_RUN_OBJS = nrun.o ## COMMON_POST_CONFIG_FRAG -interp.o: $(srcdir)/interp.c engine.c config.h +interp.o: $(srcdir)/interp.c engine.c config.h sim-main.h engine.c: gencode ./gencode @SIMCONF@ > tmp-engine diff --git a/sim/mips/interp.c b/sim/mips/interp.c index cde31b7..1e0c35e 100644 --- a/sim/mips/interp.c +++ b/sim/mips/interp.c @@ -129,80 +129,6 @@ char* pr_uword64 PARAMS ((uword64 addr)); #define AccessLength_DOUBLEWORD (7) #define AccessLength_QUADWORD (15) -/* NOTE: We cannot avoid globals, since the GDB "sim_" interface does - not allow a private variable to be passed around. This means that - simulators under GDB can only be single-threaded. However, it would - be possible for the simulators to be multi-threaded if GDB allowed - for a private pointer to be maintained. i.e. a general "void **ptr" - variable that GDB passed around in the argument list to all of - sim_xxx() routines. It could be initialised to NULL by GDB, and - then updated by sim_open() and used by the other sim_xxx() support - functions. This would allow new features in the simulator world, - like storing a context - continuing execution to gather a result, - and then going back to the point where the context was saved and - changing some state before continuing. i.e. the ability to perform - UNDOs on simulations. It would also allow the simulation of - shared-memory multi-processor systems. - - [NOTE: This is now partially implemented] */ - -/* This is nasty, since we have to rely on matching the register - numbers used by GDB. Unfortunately, depending on the MIPS target - GDB uses different register numbers. We cannot just include the - relevant "gdb/tm.h" link, since GDB may not be configured before - the sim world, and also the GDB header file requires too much other - state. */ -/* TODO: Sort out a scheme for *KNOWING* the mapping between real - registers, and the numbers that GDB uses. At the moment due to the - order that the tools are built, we cannot rely on a configured GDB - world whilst constructing the simulator. This means we have to - assume the GDB register number mapping. */ -#ifndef TM_MIPS_H -#define LAST_EMBED_REGNUM (89) -#define NUM_REGS (LAST_EMBED_REGNUM + 1) -/* start-sanitize-r5900 */ -#undef NUM_REGS -#define NUM_REGS (128) -/* end-sanitize-r5900 */ -#endif - -/* To keep this default simulator simple, and fast, we use a direct - vector of registers. The internal simulator engine then uses - manifests to access the correct slot. */ -static ut_reg registers[LAST_EMBED_REGNUM + 1]; -static int register_widths[NUM_REGS]; - -#define GPR (®isters[0]) -#if defined(HASFPU) -#define FGRIDX (38) -#define FGR (®isters[FGRIDX]) -#endif /* HASFPU */ -#define LO (registers[33]) -#define HI (registers[34]) -#define PC (registers[37]) -#define CAUSE (registers[36]) -#define SRIDX (32) -#define SR (registers[SRIDX]) /* CPU status register */ -#define FCR0IDX (71) -#define FCR0 (registers[FCR0IDX]) /* really a 32bit register */ -#define FCR31IDX (70) -#define FCR31 (registers[FCR31IDX]) /* really a 32bit register */ -#define FCSR (FCR31) -#define Debug (registers[86]) -#define DEPC (registers[87]) -#define EPC (registers[88]) -#define COCIDX (LAST_EMBED_REGNUM + 2) /* special case : outside the normal range */ - -/* The following are pseudonyms for standard registers */ -#define ZERO (registers[0]) -#define V0 (registers[2]) -#define A0 (registers[4]) -#define A1 (registers[5]) -#define A2 (registers[6]) -#define A3 (registers[7]) -#define SP (registers[29]) -#define RA (registers[31]) - /* Bits in the Debug register */ #define Debug_DBD 0x80000000 /* Debug Branch Delay */ @@ -212,37 +138,20 @@ static int register_widths[NUM_REGS]; /* start-sanitize-r5900 */ -/* -The R5900 has 128 bit registers, but the hi 64 bits are only touched by -multimedia (MMI) instructions. The normal mips instructions just use the -lower 64 bits. To avoid changing the older parts of the simulator to -handle this weirdness, the high 64 bits of each register are kept in -a separate array (registers1). The high 64 bits of any register are by -convention refered by adding a '1' to the end of the normal register's -name. So LO still refers to the low 64 bits of the LO register, LO1 -refers to the high 64 bits of that same register. -*/ - -/* The high part of each register */ -static ut_reg registers1[LAST_EMBED_REGNUM + 1]; - -#define GPR1 (®isters1[0]) -#define LO1 (registers1[32]) -#define HI1 (registers1[33]) -#define REGISTER_SA (124) - -#define BYTES_IN_MMI_REGS (sizeof(registers[0])+sizeof(registers1[0])) +#define BYTES_IN_MMI_REGS (sizeof(signed_word) + sizeof(signed_word)) #define HALFWORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/2) #define WORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/4) #define DOUBLEWORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/8) -#define BYTES_IN_MIPS_REGS (sizeof(registers[0])) +#define BYTES_IN_MIPS_REGS (sizeof(signed_word)) #define HALFWORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/2) #define WORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/4) #define DOUBLEWORDS_IN_MIPS_REGS (BYTES_IN_MIPS_REGS/8) + + /* SUB_REG_FETCH - return as lvalue some sub-part of a "register" T - type of the sub part @@ -277,15 +186,15 @@ GPR_<type>(R,I) - return, as lvalue, the I'th <type> of general register R #define SUB_REG_UW(A,A1,I) SUB_REG_FETCH(unsigned32, WORDS_IN_MIPS_REGS, A, A1, I) #define SUB_REG_UD(A,A1,I) SUB_REG_FETCH(unsigned64, DOUBLEWORDS_IN_MIPS_REGS, A, A1, I) -#define GPR_SB(R,I) SUB_REG_SB(®isters[R], ®isters1[R], I) -#define GPR_SH(R,I) SUB_REG_SH(®isters[R], ®isters1[R], I) -#define GPR_SW(R,I) SUB_REG_SW(®isters[R], ®isters1[R], I) -#define GPR_SD(R,I) SUB_REG_SD(®isters[R], ®isters1[R], I) +#define GPR_SB(R,I) SUB_REG_SB(®ISTERS[R], ®ISTERS1[R], I) +#define GPR_SH(R,I) SUB_REG_SH(®ISTERS[R], ®ISTERS1[R], I) +#define GPR_SW(R,I) SUB_REG_SW(®ISTERS[R], ®ISTERS1[R], I) +#define GPR_SD(R,I) SUB_REG_SD(®ISTERS[R], ®ISTERS1[R], I) -#define GPR_UB(R,I) SUB_REG_UB(®isters[R], ®isters1[R], I) -#define GPR_UH(R,I) SUB_REG_UH(®isters[R], ®isters1[R], I) -#define GPR_UW(R,I) SUB_REG_UW(®isters[R], ®isters1[R], I) -#define GPR_UD(R,I) SUB_REG_UD(®isters[R], ®isters1[R], I) +#define GPR_UB(R,I) SUB_REG_UB(®ISTERS[R], ®ISTERS1[R], I) +#define GPR_UH(R,I) SUB_REG_UH(®ISTERS[R], ®ISTERS1[R], I) +#define GPR_UW(R,I) SUB_REG_UW(®ISTERS[R], ®ISTERS1[R], I) +#define GPR_UD(R,I) SUB_REG_UD(®ISTERS[R], ®ISTERS1[R], I) #define RS_SB(I) SUB_REG_SB(&rs_reg, &rs_reg1, I) @@ -332,20 +241,6 @@ GPR_<type>(R,I) - return, as lvalue, the I'th <type> of general register R /* end-sanitize-r5900 */ -/* start-sanitize-r5900 */ -static ut_reg SA; /* the shift amount register */ -/* end-sanitize-r5900 */ - -#if defined(HASFPU) -/* Keep the current format state for each register: */ -static FP_formats fpr_state[32]; -#endif /* HASFPU */ - -/* The following are internal simulator state variables: */ -static ut_reg IPC = 0; /* internal Instruction PC */ -static ut_reg DSPC = 0; /* delay-slot PC */ - - /* TODO : these should be the bitmasks for these bits within the status register. At the moment the following are VR4300 bit-positions: */ @@ -381,7 +276,7 @@ static ut_reg DSPC = 0; /* delay-slot PC */ /* This should be the COC1 value at the start of the preceding instruction: */ -#define PREVCOC1() ((state & simPCOC1) ? 1 : 0) +#define PREVCOC1() ((STATE & simPCOC1) ? 1 : 0) #endif /* HASFPU */ /* Standard FCRS bits: */ @@ -413,25 +308,12 @@ static ut_reg DSPC = 0; /* delay-slot PC */ #define FP_RM_TOMINF (3) /* Round to Minus infinity (Floor) */ #define GETRM() (int)((FCSR >> FP_SH_RM) & FP_MASK_RM) -/* 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 */ -static int pending_in; -static int pending_out; -static int pending_total; -static int pending_slot_count[PSLOTS]; -static int pending_slot_reg[PSLOTS]; -static ut_reg pending_slot_value[PSLOTS]; - /*---------------------------------------------------------------------------*/ /*-- GDB simulator interface ------------------------------------------------*/ /*---------------------------------------------------------------------------*/ -static void dotrace PARAMS((FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...)); -static void ColdReset PARAMS((void)); +static void dotrace PARAMS((SIM_DESC sd,FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...)); +static void ColdReset PARAMS((SIM_DESC sd)); static long getnum PARAMS((SIM_DESC sd, char *value)); static unsigned int power2 PARAMS((unsigned int value)); static void mips_set_profile PARAMS((SIM_DESC sd, int n)); @@ -442,52 +324,20 @@ static void mips_size PARAMS((SIM_DESC sd, int n)); /* 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))\ +/* 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);\ + 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_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);*/\ } -static int LLBIT = 0; -/* LLBIT = Load-Linked bit. A bit of "virtual" state used by atomic - read-write instructions. It is set when a linked load occurs. It is - tested and cleared by the conditional store. It is cleared (during - other CPU operations) when a store to the location would no longer - be atomic. In particular, it is cleared by exception return - instructions. */ - -static int HIACCESS = 0; -static int LOACCESS = 0; -static int HI1ACCESS = 0; -static int LO1ACCESS = 0; - -/* ??? 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. */ -#if 1 -#define CHECKHILO(s) -#else -/* 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. */ -static ut_reg HLPC = 0; -/* 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) || (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 /* NOTE: We keep the following status flags as bit values (1 for true, 0 for false). This allows them to be used in binary boolean @@ -525,6 +375,7 @@ static ut_reg HLPC = 0; /* At the moment these values will be the same, since we do not have access to the pipeline cycle count information from the simulator engine. */ +/* FIXME: These will be replaced by ../common/sim-profile.h */ static unsigned int instruction_fetches = 0; static unsigned int instruction_fetch_overflow = 0; #endif @@ -541,32 +392,29 @@ static unsigned int instruction_fetch_overflow = 0; #define simSIGINT (1 << 28) /* 0 = do nothing; 1 = SIGINT has occured */ #define simJALDELAYSLOT (1 << 29) /* 1 = in jal delay slot */ -static unsigned int state = 0; -static unsigned int dsstate; - #define DELAYSLOT() {\ - if (state & simDELAYSLOT)\ + if (STATE & simDELAYSLOT)\ sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\ - state |= simDELAYSLOT;\ + STATE |= simDELAYSLOT;\ } #define JALDELAYSLOT() {\ DELAYSLOT ();\ - state |= simJALDELAYSLOT;\ + STATE |= simJALDELAYSLOT;\ } #define NULLIFY() {\ - state &= ~simDELAYSLOT;\ - state |= simSKIPNEXT;\ + STATE &= ~simDELAYSLOT;\ + STATE |= simSKIPNEXT;\ } #define CANCELDELAYSLOT() {\ - dsstate = 0;\ - state &= ~(simDELAYSLOT | simJALDELAYSLOT);\ + DSSTATE = 0;\ + STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\ } -#define INDELAYSLOT() ((state & simDELAYSLOT) != 0) -#define INJALDELAYSLOT() ((state & simJALDELAYSLOT) != 0) +#define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0) +#define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0) #define K0BASE (0x80000000) #define K0SIZE (0x20000000) @@ -629,11 +477,11 @@ mips_option_handler (sd, opt, arg) (i.e. only from main onwards, excluding the run-time setup, etc.). */ if (arg == NULL) - state |= simTRACE; + STATE |= simTRACE; else if (strcmp (arg, "yes") == 0) - state |= simTRACE; + STATE |= simTRACE; else if (strcmp (arg, "no") == 0) - state &= ~simTRACE; + STATE &= ~simTRACE; else { fprintf (stderr, "Unreconized trace option `%s'\n", arg); @@ -668,7 +516,7 @@ Re-compile simulator with \"-DTRACE\" to enable this option.\n"); case 'p': #if defined(PROFILE) - state |= simPROFILE; + STATE |= simPROFILE; return SIM_RC_OK; #else /* !PROFILE */ fprintf(stderr,"\ @@ -749,6 +597,7 @@ sim_open (kind, cb, abfd, argv) char **argv; { SIM_DESC sd = sim_state_alloc (kind, cb); + sim_cpu *cpu = STATE_CPU (sd, 0); /* FIXME: watchpoints code shouldn't need this */ STATE_WATCHPOINTS (sd)->pc = &(PC); @@ -760,7 +609,7 @@ sim_open (kind, cb, abfd, argv) STATE_MEM_SIZE (sd) = (2 << 20); STATE_MEM_BASE (sd) = K1BASE; - state = 0; + STATE = 0; if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK) return 0; @@ -845,23 +694,21 @@ sim_open (kind, cb, abfd, argv) int rn; for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++) { if (rn < 32) - register_widths[rn] = GPRLEN; -#if defined(HASFPU) + cpu->register_widths[rn] = GPRLEN; else if ((rn >= FGRIDX) && (rn < (FGRIDX + 32))) - register_widths[rn] = GPRLEN; -#endif + cpu->register_widths[rn] = GPRLEN; else if ((rn >= 33) && (rn <= 37)) - register_widths[rn] = GPRLEN; + cpu->register_widths[rn] = GPRLEN; else if ((rn == SRIDX) || (rn == FCR0IDX) || (rn == FCR31IDX) || ((rn >= 72) && (rn <= 89))) - register_widths[rn] = 32; + cpu->register_widths[rn] = 32; else - register_widths[rn] = 0; + cpu->register_widths[rn] = 0; } /* start-sanitize-r5900 */ /* set the 5900 "upper" registers to 64 bits */ for( rn = LAST_EMBED_REGNUM+1; rn < NUM_REGS; rn++) - register_widths[rn] = 64; + cpu->register_widths[rn] = 64; /* end-sanitize-r5900 */ } @@ -896,7 +743,7 @@ sim_open (kind, cb, abfd, argv) monitor_size); #if defined(TRACE) - if (state & simTRACE) + if (STATE & simTRACE) open_trace(sd); #endif /* TRACE */ @@ -1064,7 +911,7 @@ sim_close (sd, quitting) sim_io_shutdown (sd); #if defined(PROFILE) - if ((state & simPROFILE) && (profile_hist != NULL)) { + if ((STATE & simPROFILE) && (profile_hist != NULL)) { FILE *pf = fopen("gmon.out","wb"); unsigned loop; @@ -1095,7 +942,7 @@ sim_close (sd, quitting) free(profile_hist); profile_hist = NULL; - state &= ~simPROFILE; + STATE &= ~simPROFILE; } #endif /* PROFILE */ @@ -1103,7 +950,7 @@ sim_close (sd, quitting) if (tracefh != NULL && tracefh != stderr) fclose(tracefh); tracefh = NULL; - state &= ~simTRACE; + STATE &= ~simTRACE; #endif /* TRACE */ if (logfh != NULL && logfh != stdout && logfh != stderr) @@ -1267,6 +1114,7 @@ sim_store_register (sd,rn,memory) int rn; unsigned char *memory; { + sim_cpu *cpu = STATE_CPU (sd, 0); /* NOTE: gdb (the client) stores registers in target byte order while the simulator uses host byte order */ #ifdef DEBUG @@ -1277,18 +1125,18 @@ sim_store_register (sd,rn,memory) numbering one. We need to know what the width of each logical register number is for the architecture being simulated. */ - if (register_widths[rn] == 0) + if (cpu->register_widths[rn] == 0) sim_io_eprintf(sd,"Invalid register width for %d (register store ignored)\n",rn); /* start-sanitize-r5900 */ else if (rn == REGISTER_SA) SA = T2H_8(*(uword64*)memory); else if (rn > LAST_EMBED_REGNUM) - registers1[rn - LAST_EMBED_REGNUM - 1] = T2H_8(*(uword64*)memory); + cpu->registers1[rn - LAST_EMBED_REGNUM - 1] = T2H_8(*(uword64*)memory); /* end-sanitize-r5900 */ - else if (register_widths[rn] == 32) - registers[rn] = T2H_4 (*(unsigned int*)memory); + else if (cpu->register_widths[rn] == 32) + cpu->registers[rn] = T2H_4 (*(unsigned int*)memory); else - registers[rn] = T2H_8 (*(uword64*)memory); + cpu->registers[rn] = T2H_8 (*(uword64*)memory); return; } @@ -1299,24 +1147,25 @@ sim_fetch_register (sd,rn,memory) int rn; unsigned char *memory; { + sim_cpu *cpu = STATE_CPU (sd, 0); /* NOTE: gdb (the client) stores registers in target byte order while the simulator uses host byte order */ #ifdef DEBUG sim_io_printf(sd,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn,pr_addr(registers[rn])); #endif /* DEBUG */ - if (register_widths[rn] == 0) + if (cpu->register_widths[rn] == 0) sim_io_eprintf(sd,"Invalid register width for %d (register fetch ignored)\n",rn); /* start-sanitize-r5900 */ else if (rn == REGISTER_SA) *((uword64 *)memory) = H2T_8(SA); else if (rn > LAST_EMBED_REGNUM) - *((uword64 *)memory) = H2T_8(registers1[rn - LAST_EMBED_REGNUM - 1]); + *((uword64 *)memory) = H2T_8(cpu->registers1[rn - LAST_EMBED_REGNUM - 1]); /* end-sanitize-r5900 */ - else if (register_widths[rn] == 32) - *((unsigned int *)memory) = H2T_4 ((unsigned int)(registers[rn] & 0xFFFFFFFF)); + else if (cpu->register_widths[rn] == 32) + *((unsigned int *)memory) = H2T_4 ((unsigned int)(cpu->registers[rn] & 0xFFFFFFFF)); else /* 64bit register */ - *((uword64 *)memory) = H2T_8 (registers[rn]); + *((uword64 *)memory) = H2T_8 (cpu->registers[rn]); return; } @@ -1384,7 +1233,7 @@ sim_create_inferior (sd, abfd, argv,env) pr_addr(PC)); #endif /* DEBUG */ - ColdReset(); + ColdReset(sd); /* If we were providing a more complete I/O, co-processor or memory simulation, we should perform any "device" initialisation at this point. This can include pre-loading memory areas with particular @@ -1468,7 +1317,7 @@ sim_do_command (sd,cmd) break; case e_reset: /* no arguments */ - ColdReset(); + ColdReset(sd); /* NOTE: See the comments in sim_open() relating to device initialisation. */ break; @@ -1504,7 +1353,7 @@ mips_set_profile (sd,n) { #if defined(PROFILE) profile_frequency = n; - state |= simPROFILE; + STATE |= simPROFILE; #endif /* PROFILE */ return; } @@ -1515,7 +1364,7 @@ mips_set_profile_size (sd,n) int n; { #if defined(PROFILE) - if (state & simPROFILE) { + if (STATE & simPROFILE) { int bsize; /* Since we KNOW that the memory banks are a power-of-2 in size: */ @@ -1538,7 +1387,7 @@ mips_set_profile_size (sd,n) profile_hist = (unsigned short *)realloc(profile_hist,bsize); if (profile_hist == NULL) { sim_io_eprintf(sd,"Failed to allocate VM for profiling buffer (0x%08X bytes)\n",bsize); - state &= ~simPROFILE; + STATE &= ~simPROFILE; } } #endif /* PROFILE */ @@ -1893,7 +1742,8 @@ load_word (sd, vaddr) code, but for ease of simulation we just handle them directly. */ static void -mips16_entry (insn) +mips16_entry (sd,insn) + SIM_DESC sd; unsigned int insn; { int aregs, sregs, rreg; @@ -1918,7 +1768,7 @@ mips16_entry (insn) /* This is the entry pseudo-instruction. */ for (i = 0; i < aregs; i++) - store_word ((uword64) (SP + 4 * i), registers[i + 4]); + store_word ((uword64) (SP + 4 * i), GPR[i + 4]); tsp = SP; SP -= 32; @@ -1932,7 +1782,7 @@ mips16_entry (insn) for (i = 0; i < sregs; i++) { tsp -= 4; - store_word ((uword64) tsp, registers[16 + i]); + store_word ((uword64) tsp, GPR[16 + i]); } } else @@ -1953,7 +1803,7 @@ mips16_entry (insn) for (i = 0; i < sregs; i++) { tsp -= 4; - registers[i + 16] = load_word ((uword64) tsp); + GPR[i + 16] = load_word ((uword64) tsp); } SP += 32; @@ -1962,14 +1812,14 @@ mips16_entry (insn) if (aregs == 5) { FGR[0] = WORD64LO (GPR[4]); - fpr_state[0] = fmt_uninterpreted; + FPR_STATE[0] = fmt_uninterpreted; } else if (aregs == 6) { FGR[0] = WORD64LO (GPR[5]); FGR[1] = WORD64LO (GPR[4]); - fpr_state[0] = fmt_uninterpreted; - fpr_state[1] = fmt_uninterpreted; + FPR_STATE[0] = fmt_uninterpreted; + FPR_STATE[1] = fmt_uninterpreted; } #endif /* defined(HASFPU) */ @@ -2059,9 +1909,9 @@ getnum(sd,value) static -void dotrace(FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...) +void dotrace(SIM_DESC sd,FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,...) { - if (state & simTRACE) { + if (STATE & simTRACE) { va_list ap; fprintf(tracefh,"%d %s ; width %d ; ", type, @@ -2095,7 +1945,8 @@ void dotrace(FILE *tracefh,int type,SIM_ADDR address,int width,char *comment,... /*---------------------------------------------------------------------------*/ static void -ColdReset() +ColdReset(sd) + SIM_DESC sd; { /* RESET: Fixed PC address: */ PC = (((uword64)0xFFFFFFFF<<32) | 0xBFC00000); @@ -2114,8 +1965,8 @@ ColdReset() { int loop; for (loop = 0; (loop < PSLOTS); loop++) - pending_slot_reg[loop] = (LAST_EMBED_REGNUM + 1); - pending_in = pending_out = pending_total = 0; + PENDING_SLOT_REG[loop] = (LAST_EMBED_REGNUM + 1); + PENDING_IN = PENDING_OUT = PENDING_TOTAL = 0; } #if defined(HASFPU) @@ -2123,7 +1974,7 @@ ColdReset() { int rn; for (rn = 0; (rn < 32); rn++) - fpr_state[rn] = fmt_uninterpreted; + FPR_STATE[rn] = fmt_uninterpreted; } #endif /* HASFPU */ @@ -2305,7 +2156,7 @@ load_memory(sd,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw) #if defined(TRACE) if (!raw) - dotrace(tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction")); + dotrace(sd,tracefh,((IorD == isDATA) ? 0 : 2),(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"load%s",((IorD == isDATA) ? "" : " instruction")); #endif /* TRACE */ /* NOTE: Quicker methods of decoding the address space can be used @@ -2477,7 +2328,7 @@ store_memory(sd,CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw) #if defined(TRACE) if (!raw) - dotrace(tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store"); + dotrace(sd,tracefh,1,(unsigned int)(pAddr&0xFFFFFFFF),(AccessLength + 1),"store"); #endif /* TRACE */ /* See the comments in the LoadMemory routine about optimising @@ -2755,7 +2606,7 @@ signal_exception (SIM_DESC sd, int exception,...) sim_exited, (unsigned int)(A0 & 0xFFFFFFFF)); } } - if (state & simDELAYSLOT) + if (STATE & simDELAYSLOT) PC = IPC - 4; /* reference the branch instruction */ else PC = IPC; @@ -2773,9 +2624,9 @@ signal_exception (SIM_DESC sd, int exception,...) if (! (SR & status_EXL)) { CAUSE = (exception << 2); - if (state & simDELAYSLOT) + if (STATE & simDELAYSLOT) { - state &= ~simDELAYSLOT; + STATE &= ~simDELAYSLOT; CAUSE |= cause_BD; EPC = (IPC - 4); /* reference the branch instruction */ } @@ -3038,24 +2889,24 @@ value_fpr(sd,fpr,fmt) #if 1 /* If request to read data as "uninterpreted", then use the current encoding: */ - fmt = fpr_state[fpr]; + fmt = FPR_STATE[fpr]; #else fmt = fmt_long; #endif /* For values not yet accessed, set to the desired format: */ - if (fpr_state[fpr] == fmt_uninterpreted) { - fpr_state[fpr] = fmt; + if (FPR_STATE[fpr] == fmt_uninterpreted) { + FPR_STATE[fpr] = fmt; #ifdef DEBUG printf("DBG: Register %d was fmt_uninterpreted. Now %s\n",fpr,DOFMT(fmt)); #endif /* DEBUG */ } - if (fmt != fpr_state[fpr]) { - sim_io_eprintf(sd,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr,DOFMT(fpr_state[fpr]),DOFMT(fmt),pr_addr(IPC)); - fpr_state[fpr] = fmt_unknown; + if (fmt != FPR_STATE[fpr]) { + sim_io_eprintf(sd,"FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)\n",fpr,DOFMT(FPR_STATE[fpr]),DOFMT(fmt),pr_addr(IPC)); + FPR_STATE[fpr] = fmt_unknown; } - if (fpr_state[fpr] == fmt_unknown) { + if (FPR_STATE[fpr] == fmt_unknown) { /* Set QNaN value: */ switch (fmt) { case fmt_single: @@ -3146,18 +2997,18 @@ store_fpr(sd,fpr,fmt,value) case fmt_single : case fmt_word : FGR[fpr] = (((uword64)0xDEADC0DE << 32) | (value & 0xFFFFFFFF)); - fpr_state[fpr] = fmt; + FPR_STATE[fpr] = fmt; break; case fmt_uninterpreted: case fmt_double : case fmt_long : FGR[fpr] = value; - fpr_state[fpr] = fmt; + FPR_STATE[fpr] = fmt; break; default : - fpr_state[fpr] = fmt_unknown; + FPR_STATE[fpr] = fmt_unknown; err = -1; break; } @@ -3166,7 +3017,7 @@ store_fpr(sd,fpr,fmt,value) case fmt_single : case fmt_word : FGR[fpr] = (value & 0xFFFFFFFF); - fpr_state[fpr] = fmt; + FPR_STATE[fpr] = fmt; break; case fmt_uninterpreted: @@ -3175,17 +3026,17 @@ store_fpr(sd,fpr,fmt,value) if ((fpr & 1) == 0) { /* even register number only */ FGR[fpr+1] = (value >> 32); FGR[fpr] = (value & 0xFFFFFFFF); - fpr_state[fpr + 1] = fmt; - fpr_state[fpr] = fmt; + FPR_STATE[fpr + 1] = fmt; + FPR_STATE[fpr] = fmt; } else { - fpr_state[fpr] = fmt_unknown; - fpr_state[fpr + 1] = fmt_unknown; + FPR_STATE[fpr] = fmt_unknown; + FPR_STATE[fpr + 1] = fmt_unknown; SignalException(ReservedInstruction,0); } break; default : - fpr_state[fpr] = fmt_unknown; + FPR_STATE[fpr] = fmt_unknown; err = -1; break; } @@ -3910,7 +3761,7 @@ cop_lw(sd,coproc_num,coproc_reg,memword) printf("DBG: COP_LW: memword = 0x%08X (uword64)memword = 0x%s\n",memword,pr_addr(memword)); #endif StoreFPR(coproc_reg,fmt_word,(uword64)memword); - fpr_state[coproc_reg] = fmt_uninterpreted; + FPR_STATE[coproc_reg] = fmt_uninterpreted; break; #endif /* HASFPU */ @@ -3960,17 +3811,17 @@ cop_sw(sd,coproc_num,coproc_reg) #if 1 { FP_formats hold; - hold = fpr_state[coproc_reg]; - fpr_state[coproc_reg] = fmt_word; + hold = FPR_STATE[coproc_reg]; + FPR_STATE[coproc_reg] = fmt_word; value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted); - fpr_state[coproc_reg] = hold; + FPR_STATE[coproc_reg] = hold; } #else #if 1 - value = (unsigned int)ValueFPR(coproc_reg,fpr_state[coproc_reg]); + value = (unsigned int)ValueFPR(coproc_reg,FPR_STATE[coproc_reg]); #else #ifdef DEBUG - printf("DBG: COP_SW: reg in format %s (will be accessing as single)\n",DOFMT(fpr_state[coproc_reg])); + printf("DBG: COP_SW: reg in format %s (will be accessing as single)\n",DOFMT(FPR_STATE[coproc_reg])); #endif /* DEBUG */ value = (unsigned int)ValueFPR(coproc_reg,fmt_single); #endif @@ -4001,10 +3852,10 @@ cop_sd(sd,coproc_num,coproc_reg) value = ValueFPR(coproc_reg,fmt_uninterpreted); #else #if 1 - value = ValueFPR(coproc_reg,fpr_state[coproc_reg]); + value = ValueFPR(coproc_reg,FPR_STATE[coproc_reg]); #else #ifdef DEBUG - printf("DBG: COP_SD: reg in format %s (will be accessing as double)\n",DOFMT(fpr_state[coproc_reg])); + printf("DBG: COP_SD: reg in format %s (will be accessing as double)\n",DOFMT(FPR_STATE[coproc_reg])); #endif /* DEBUG */ value = ValueFPR(coproc_reg,fmt_double); #endif @@ -4218,7 +4069,7 @@ sim_engine_run (sd, next_cpu_nr, siggnal) } #endif /* DEBUG */ - dsstate = (state & simDELAYSLOT); + DSSTATE = (STATE & simDELAYSLOT); #ifdef DEBUG if (dsstate) sim_io_printf(sd,"DBG: DSPC = 0x%s\n",pr_addr(DSPC)); @@ -4265,7 +4116,7 @@ sim_engine_run (sd, next_cpu_nr, siggnal) if (instruction_fetches == 0) instruction_fetch_overflow++; #if defined(PROFILE) - if ((state & simPROFILE) && ((instruction_fetches % profile_frequency) == 0) && profile_hist) { + if ((STATE & simPROFILE) && ((instruction_fetches % profile_frequency) == 0) && profile_hist) { unsigned n = ((unsigned int)(PC - profile_minpc) >> (profile_shift + 2)); if (n < profile_nsamples) { /* NOTE: The counts for the profiling bins are only 16bits wide */ @@ -4324,15 +4175,15 @@ sim_engine_run (sd, next_cpu_nr, siggnal) #if defined(HASFPU) /* Set previous flag, depending on current: */ - if (state & simPCOC0) - state |= simPCOC1; + if (STATE & simPCOC0) + STATE |= simPCOC1; else - state &= ~simPCOC1; + STATE &= ~simPCOC1; /* and update the current value: */ if (GETFCC(0)) - state |= simPCOC0; + STATE |= simPCOC0; else - state &= ~simPCOC0; + STATE &= ~simPCOC0; #endif /* HASFPU */ /* NOTE: For multi-context simulation environments the "instruction" @@ -4342,7 +4193,7 @@ sim_engine_run (sd, next_cpu_nr, siggnal) variables (and a single-threaded simulator engine), then we can create the actual variables with these names. */ - if (!(state & simSKIPNEXT)) { + if (!(STATE & simSKIPNEXT)) { /* Include the simulator engine */ #include "engine.c" #if ((GPRLEN == 64) && !PROCESSOR_64BIT) || ((GPRLEN == 32) && PROCESSOR_64BIT) @@ -4378,11 +4229,11 @@ sim_engine_run (sd, next_cpu_nr, siggnal) ZERO = 0; /* reset back to zero before next instruction */ } } else /* simSKIPNEXT check */ - state &= ~simSKIPNEXT; + STATE &= ~simSKIPNEXT; /* If the delay slot was active before the instruction is executed, then update the PC to its new value: */ - if (dsstate) { + if (DSSTATE) { #ifdef DEBUG printf("DBG: dsstate set before instruction execution - updating PC to 0x%s\n",pr_addr(DSPC)); #endif /* DEBUG */ @@ -4395,11 +4246,11 @@ sim_engine_run (sd, next_cpu_nr, siggnal) #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) { + if (PENDING_OUT != PENDING_IN) { int loop; - int index = pending_out; - int total = pending_total; - if (pending_total == 0) { + int index = PENDING_OUT; + int total = PENDING_TOTAL; + if (PENDING_TOTAL == 0) { fprintf(stderr,"FATAL: Mis-match on pending update pointers\n"); exit(1); } @@ -4407,39 +4258,39 @@ sim_engine_run (sd, next_cpu_nr, siggnal) #ifdef DEBUG printf("DBG: BEFORE index = %d, loop = %d\n",index,loop); #endif /* DEBUG */ - if (pending_slot_reg[index] != (LAST_EMBED_REGNUM + 1)) { + if (PENDING_SLOT_REG[index] != (LAST_EMBED_REGNUM + 1)) { #ifdef DEBUG - printf("pending_slot_count[%d] = %d\n",index,pending_slot_count[index]); + printf("pending_slot_count[%d] = %d\n",index,PENDING_SLOT_COUNT[index]); #endif /* DEBUG */ - if (--(pending_slot_count[index]) == 0) { + 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])); + 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 (PENDING_SLOT_REG[index] == COCIDX) { #if defined(HASFPU) SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); #else ; #endif } else { - registers[pending_slot_reg[index]] = pending_slot_value[index]; + REGISTERS[PENDING_SLOT_REG[index]] = PENDING_SLOT_VALUE[index]; #if defined(HASFPU) /* 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; + if ((PENDING_SLOT_REG[index] >= FGRIDX) && (PENDING_SLOT_REG[index] < (FGRIDX + 32))) + FPR_STATE[PENDING_SLOT_REG[index] - FGRIDX] = fmt_uninterpreted; #endif /* HASFPU */ } #ifdef DEBUG - printf("registers[%d] = 0x%s\n",pending_slot_reg[index],pr_addr(registers[pending_slot_reg[index]])); + 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--; + PENDING_SLOT_REG[index] = (LAST_EMBED_REGNUM + 1); + PENDING_OUT++; + if (PENDING_OUT == PSLOTS) + PENDING_OUT = 0; + PENDING_TOTAL--; } } #ifdef DEBUG @@ -4451,7 +4302,7 @@ sim_engine_run (sd, next_cpu_nr, siggnal) } } #ifdef DEBUG - printf("DBG: EMPTY AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",pending_in,pending_out,pending_total); + printf("DBG: EMPTY AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL); #endif /* DEBUG */ } diff --git a/sim/mips/sim-main.h b/sim/mips/sim-main.h index f5356bd..f1dd362 100644 --- a/sim/mips/sim-main.h +++ b/sim/mips/sim-main.h @@ -78,8 +78,215 @@ typedef unsigned64 uword64; #endif -/* FIXME: At present the CPU registers are static */ +/* Floating-point operations: */ + +/* FPU registers must be one of the following types. All other values + are reserved (and undefined). */ +typedef enum { + fmt_single = 0, + fmt_double = 1, + fmt_word = 4, + fmt_long = 5, + /* The following are well outside the normal acceptable format + range, and are used in the register status vector. */ + fmt_unknown = 0x10000000, + fmt_uninterpreted = 0x20000000, +} FP_formats; + +unsigned64 value_fpr PARAMS ((SIM_DESC sd, int fpr, FP_formats)); +#define ValueFPR(FPR,FMT) value_fpr (sd, (FPR), (FMT)) + +void store_fpr PARAMS ((SIM_DESC sd, int fpr, FP_formats fmt, unsigned64 value)); +#define StoreFPR(FPR,FMT,VALUE) store_fpr (sd, (FPR), (FMT), (VALUE)) + +int NaN PARAMS ((unsigned64 op, FP_formats fmt)); +int Infinity PARAMS ((unsigned64 op, FP_formats fmt)); +int Less PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +int Equal PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 AbsoluteValue PARAMS ((unsigned64 op, FP_formats fmt)); +unsigned64 Negate PARAMS ((unsigned64 op, FP_formats fmt)); +unsigned64 Add PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 Sub PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 Multiply PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 Divide PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); +unsigned64 Recip PARAMS ((unsigned64 op, FP_formats fmt)); +unsigned64 SquareRoot PARAMS ((unsigned64 op, FP_formats fmt)); +unsigned64 convert PARAMS ((SIM_DESC sd, int rm, unsigned64 op, FP_formats from, FP_formats to)); +#define Convert(rm,op,from,to) convert(sd,rm,op,from,to) + + + + struct _sim_cpu { + + + /* The following are internal simulator state variables: */ + address_word ipc; /* internal Instruction PC */ + address_word dspc; /* delay-slot PC */ +#define IPC ((STATE_CPU (sd,0))->ipc) +#define DSPC ((STATE_CPU (sd,0))->dspc) + + + /* State of the simulator */ + unsigned int state; + unsigned int dsstate; +#define STATE ((STATE_CPU (sd,0))->state) +#define DSSTATE ((STATE_CPU (sd,0))->dsstate) + + +/* This is nasty, since we have to rely on matching the register + numbers used by GDB. Unfortunately, depending on the MIPS target + GDB uses different register numbers. We cannot just include the + relevant "gdb/tm.h" link, since GDB may not be configured before + the sim world, and also the GDB header file requires too much other + state. */ + +#ifndef TM_MIPS_H +#define LAST_EMBED_REGNUM (89) +#define NUM_REGS (LAST_EMBED_REGNUM + 1) +/* start-sanitize-r5900 */ +#undef NUM_REGS +#define NUM_REGS (128) +/* end-sanitize-r5900 */ +#endif + +/* To keep this default simulator simple, and fast, we use a direct + vector of registers. The internal simulator engine then uses + manifests to access the correct slot. */ + + signed_word registers[LAST_EMBED_REGNUM + 1]; + int register_widths[NUM_REGS]; +#define REGISTERS ((STATE_CPU (sd,0))->registers) + +#define GPR (®ISTERS[0]) +#define FGRIDX (38) +#define FGR (®ISTERS[FGRIDX]) +#define LO (REGISTERS[33]) +#define HI (REGISTERS[34]) +#define PC (REGISTERS[37]) +#define CAUSE (REGISTERS[36]) +#define SRIDX (32) +#define SR (REGISTERS[SRIDX]) /* CPU status register */ +#define FCR0IDX (71) +#define FCR0 (REGISTERS[FCR0IDX]) /* really a 32bit register */ +#define FCR31IDX (70) +#define FCR31 (REGISTERS[FCR31IDX]) /* really a 32bit register */ +#define FCSR (FCR31) +#define Debug (REGISTERS[86]) +#define DEPC (REGISTERS[87]) +#define EPC (REGISTERS[88]) +#define COCIDX (LAST_EMBED_REGNUM + 2) /* special case : outside the normal range */ + +/* The following are pseudonyms for standard registers */ +#define ZERO (REGISTERS[0]) +#define V0 (REGISTERS[2]) +#define A0 (REGISTERS[4]) +#define A1 (REGISTERS[5]) +#define A2 (REGISTERS[6]) +#define A3 (REGISTERS[7]) +#define SP (REGISTERS[29]) +#define RA (REGISTERS[31]) + + /* Keep the current format state for each register: */ + FP_formats fpr_state[32]; +#define FPR_STATE ((STATE_CPU (sd, 0))->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 ((STATE_CPU (sd, 0))->pending_in) +#define PENDING_OUT ((STATE_CPU (sd, 0))->pending_out) +#define PENDING_TOTAL ((STATE_CPU (sd, 0))->pending_total) +#define PENDING_SLOT_COUNT ((STATE_CPU (sd, 0))->pending_slot_count) +#define PENDING_SLOT_REG ((STATE_CPU (sd, 0))->pending_slot_reg) +#define PENDING_SLOT_VALUE ((STATE_CPU (sd, 0))->pending_slot_value) + + + /* LLBIT = Load-Linked bit. A bit of "virtual" state used by atomic + read-write instructions. It is set when a linked load occurs. It + is tested and cleared by the conditional store. It is cleared + (during other CPU operations) when a store to the location would + no longer be atomic. In particular, it is cleared by exception + return instructions. */ + int llbit; +#define LLBIT ((STATE_CPU (sd, 0))->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 ((STATE_CPU (sd, 0))->hiaccess) +#define LOACCESS ((STATE_CPU (sd, 0))->loaccess) + /* start-sanitize-r5900 */ + int hi1access; + int lo1access; +#define HI1ACCESS ((STATE_CPU (sd, 0))->hi1access) +#define LO1ACCESS ((STATE_CPU (sd, 0))->lo1access) + /* end-sanitize-r5900 */ +#if 1 + /* 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) +#else + 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));\ +} + /* end-sanitize-r5900 */ +#undef CHECKHILO +#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));\ +} + /* end-sanitize-r5900 */ +#endif + + + /* start-sanitize-r5900 */ + /* The R5900 has 128 bit registers, but the hi 64 bits are only + touched by multimedia (MMI) instructions. The normal mips + instructions just use the lower 64 bits. To avoid changing the + older parts of the simulator to handle this weirdness, the high + 64 bits of each register are kept in a separate array + (registers1). The high 64 bits of any register are by convention + refered by adding a '1' to the end of the normal register's name. + So LO still refers to the low 64 bits of the LO register, LO1 + refers to the high 64 bits of that same register. */ + + signed_word registers1[LAST_EMBED_REGNUM + 1]; +#define REGISTERS1 ((STATE_CPU (sd, 0))->registers1) +#define GPR1 (®ISTERS1[0]) +#define LO1 (REGISTERS1[32]) +#define HI1 (REGISTERS1[33]) +#define REGISTER_SA (124) + + unsigned_word sa; /* the shift amount register */ +#define SA ((STATE_CPU (sd, 0))->sa) + + /* end-sanitize-r5900 */ + + + sim_cpu_base base; }; @@ -150,43 +357,6 @@ void signal_exception (SIM_DESC sd, int exception, ...); #define SignalExceptionCoProcessorUnusable() signal_exception (sd, CoProcessorUnusable) -/* Floating-point operations: */ - -/* FPU registers must be one of the following types. All other values - are reserved (and undefined). */ -typedef enum { - fmt_single = 0, - fmt_double = 1, - fmt_word = 4, - fmt_long = 5, - /* The following are well outside the normal acceptable format - range, and are used in the register status vector. */ - fmt_unknown = 0x10000000, - fmt_uninterpreted = 0x20000000, -} FP_formats; - -unsigned64 value_fpr PARAMS ((SIM_DESC sd, int fpr, FP_formats)); -#define ValueFPR(FPR,FMT) value_fpr (sd, (FPR), (FMT)) - -void store_fpr PARAMS ((SIM_DESC sd, int fpr, FP_formats fmt, unsigned64 value)); -#define StoreFPR(FPR,FMT,VALUE) store_fpr (sd, (FPR), (FMT), (VALUE)) - -int NaN PARAMS ((unsigned64 op, FP_formats fmt)); -int Infinity PARAMS ((unsigned64 op, FP_formats fmt)); -int Less PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); -int Equal PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); -unsigned64 AbsoluteValue PARAMS ((unsigned64 op, FP_formats fmt)); -unsigned64 Negate PARAMS ((unsigned64 op, FP_formats fmt)); -unsigned64 Add PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); -unsigned64 Sub PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); -unsigned64 Multiply PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); -unsigned64 Divide PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt)); -unsigned64 Recip PARAMS ((unsigned64 op, FP_formats fmt)); -unsigned64 SquareRoot PARAMS ((unsigned64 op, FP_formats fmt)); -unsigned64 convert PARAMS ((SIM_DESC sd, int rm, unsigned64 op, FP_formats from, FP_formats to)); -#define Convert(rm,op,from,to) convert(sd,rm,op,from,to) - - /* Co-processor accesses */ void cop_lw PARAMS ((SIM_DESC sd, int coproc_num, int coproc_reg, unsigned int memword)); |