#include <stdio.h>
#include <stdarg.h>
#include <ansidecl.h>
-#include <signal.h>
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include "callback.h" /* GDB simulator callback interface */
#include "remote-sim.h" /* GDB simulator interface */
-#include "support.h" /* internal support manifests */
-
#include "sysdep.h"
#ifndef PARAMS
char* pr_addr PARAMS ((SIM_ADDR addr));
char* pr_uword64 PARAMS ((uword64 addr));
-#ifndef SIGBUS
-#define SIGBUS SIGSEGV
-#endif
/* Get the simulator engine description, without including the code: */
#define SIM_MANIFESTS
#include "engine.c"
#undef SIM_MANIFESTS
-struct sim_state simulator;
/* The following reserved instruction value is used when a simulator
trap is required. NOTE: Care must be taken, since this value may be
#define RSVD_INSTRUCTION_ARG_MASK 0xFFFFF
-/* NOTE: These numbers depend on the processor architecture being
- simulated: */
-#define Interrupt (0)
-#define TLBModification (1)
-#define TLBLoad (2)
-#define TLBStore (3)
-#define AddressLoad (4)
-#define AddressStore (5)
-#define InstructionFetch (6)
-#define DataReference (7)
-#define SystemCall (8)
-#define BreakPoint (9)
-#define ReservedInstruction (10)
-#define CoProcessorUnusable (11)
-#define IntegerOverflow (12) /* Arithmetic overflow (IDT monitor raises SIGFPE) */
-#define Trap (13)
-#define FPE (15)
-#define Watch (23)
-
-/* The following exception code is actually private to the simulator
- world. It is *NOT* a processor feature, and is used to signal
- run-time errors in the simulator. */
-#define SimulatorFault (0xFFFFFFFF)
-
/* The following are generic to all versions of the MIPS architecture
to date: */
/* Memory Access Types (for CCA): */
#define AccessLength_DOUBLEWORD (7)
#define AccessLength_QUADWORD (15)
-#if defined(HASFPU)
-/* 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;
-#endif /* HASFPU */
-
-/* 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] */
-
-static host_callback *callback = NULL; /* handle onto the current callback structure */
-
-/* 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)
-#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[LAST_EMBED_REGNUM + 1];
+/* Bits in the Debug register */
+#define Debug_DBD 0x80000000 /* Debug Branch Delay */
+#define Debug_DM 0x40000000 /* Debug Mode */
+#define Debug_DBp 0x00000002 /* Debug Breakpoint indicator */
-#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 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])
/* 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[33])
-#define HI1 (registers1[34])
-
-#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
A - low part of "register"
A1 - high part of register
*/
-#define SUB_REG_FETCH(T,TC,A,A1,I) (*(((T*)(((I) < (TC)) ? (A) : (A1))) + ((I) % (TC))))
+#define SUB_REG_FETCH(T,TC,A,A1,I) \
+(*(((I) < (TC) ? (T*)(A) : (T*)(A1)) \
+ + (CURRENT_HOST_BYTE_ORDER == BIG_ENDIAN \
+ ? ((TC) - 1 - (I) % (TC)) \
+ : ((I) % (TC)) \
+ ) \
+ ) \
+ )
/*
GPR_<type>(R,I) - return, as lvalue, the I'th <type> of general register R
2 is B=byte H=halfword W=word D=doubleword
*/
-#define SUB_REG_SB(A,A1,I) SUB_REG_FETCH(signed char, BYTES_IN_MIPS_REGS, A, A1, I)
-#define SUB_REG_SH(A,A1,I) SUB_REG_FETCH(signed short, HALFWORDS_IN_MIPS_REGS, A, A1, I)
-#define SUB_REG_SW(A,A1,I) SUB_REG_FETCH(signed int, WORDS_IN_MIPS_REGS, A, A1, I)
-#define SUB_REG_SD(A,A1,I) SUB_REG_FETCH(signed long long, DOUBLEWORDS_IN_MIPS_REGS, A, A1, I)
-
-#define SUB_REG_UB(A,A1,I) SUB_REG_FETCH(unsigned char, BYTES_IN_MIPS_REGS, A, A1, I)
-#define SUB_REG_UH(A,A1,I) SUB_REG_FETCH(unsigned short, HALFWORDS_IN_MIPS_REGS, A, A1, I)
-#define SUB_REG_UW(A,A1,I) SUB_REG_FETCH(unsigned int, WORDS_IN_MIPS_REGS, A, A1, I)
-#define SUB_REG_UD(A,A1,I) SUB_REG_FETCH(unsigned long long,DOUBLEWORDS_IN_MIPS_REGS, A, A1, I)
-
+#define SUB_REG_SB(A,A1,I) SUB_REG_FETCH(signed8, BYTES_IN_MIPS_REGS, A, A1, I)
+#define SUB_REG_SH(A,A1,I) SUB_REG_FETCH(signed16, HALFWORDS_IN_MIPS_REGS, A, A1, I)
+#define SUB_REG_SW(A,A1,I) SUB_REG_FETCH(signed32, WORDS_IN_MIPS_REGS, A, A1, I)
+#define SUB_REG_SD(A,A1,I) SUB_REG_FETCH(signed64, DOUBLEWORDS_IN_MIPS_REGS, A, A1, I)
+#define SUB_REG_UB(A,A1,I) SUB_REG_FETCH(unsigned8, BYTES_IN_MIPS_REGS, A, A1, I)
+#define SUB_REG_UH(A,A1,I) SUB_REG_FETCH(unsigned16, HALFWORDS_IN_MIPS_REGS, A, A1, I)
+#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)
/* end-sanitize-r5900 */
-/* start-sanitize-r5900 */
-static ut_reg SA; /* the shift amount register */
-/* end-sanitize-r5900 */
-
-static ut_reg EPC = 0; /* Exception PC */
-
-#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: */
/* 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: */
#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 sim_warning PARAMS((char *fmt,...));
-extern void sim_error PARAMS((char *fmt,...));
-static void ColdReset PARAMS((void));
-static int AddressTranslation PARAMS((uword64 vAddr,int IorD,int LorS,uword64 *pAddr,int *CCA,int host,int raw));
-static void StoreMemory PARAMS((int CCA,int AccessLength,uword64 MemElem,uword64 MemElem1,uword64 pAddr,uword64 vAddr,int raw));
-static void LoadMemory PARAMS((uword64*memvalp,uword64*memval1p,int CCA,int AccessLength,uword64 pAddr,uword64 vAddr,int IorD,int raw));
-static void SignalException PARAMS((int exception,...));
-static long getnum PARAMS((char *value));
-extern void sim_set_profile PARAMS((int frequency));
+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));
+static void mips_set_profile_size PARAMS((SIM_DESC sd, int n));
+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))\
- sim_warning("Attempt to over-write pending value");\
- pending_slot_count[pending_in] = 2;\
- pending_slot_reg[pending_in] = (r);\
- pending_slot_value[pending_in] = (uword64)(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_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_warning("%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
/* 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
#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;
-
#define DELAYSLOT() {\
- if (state & simDELAYSLOT)\
- sim_warning("Delay slot already activated (branch in delay slot?)");\
- state |= simDELAYSLOT;\
+ if (STATE & simDELAYSLOT)\
+ sim_io_eprintf(sd,"Delay slot already activated (branch in delay slot?)\n");\
+ STATE |= simDELAYSLOT;\
}
#define JALDELAYSLOT() {\
DELAYSLOT ();\
- state |= simJALDELAYSLOT;\
+ STATE |= simJALDELAYSLOT;\
}
#define NULLIFY() {\
- state &= ~simDELAYSLOT;\
- state |= simSKIPNEXT;\
+ STATE &= ~simDELAYSLOT;\
+ STATE |= simSKIPNEXT;\
}
-#define INDELAYSLOT() ((state & simDELAYSLOT) != 0)
-#define INJALDELAYSLOT() ((state & simJALDELAYSLOT) != 0)
+#define CANCELDELAYSLOT() {\
+ DSSTATE = 0;\
+ STATE &= ~(simDELAYSLOT | simJALDELAYSLOT);\
+ }
+
+#define INDELAYSLOT() ((STATE & simDELAYSLOT) != 0)
+#define INJALDELAYSLOT() ((STATE & simJALDELAYSLOT) != 0)
#define K0BASE (0x80000000)
#define K0SIZE (0x20000000)
#if defined(TRACE)
static char *tracefile = "trace.din"; /* default filename for trace log */
static FILE *tracefh = NULL;
-static void open_trace PARAMS((void));
+static void open_trace PARAMS((SIM_DESC sd));
#endif /* TRACE */
#if defined(PROFILE)
char *tmp;
tmp = (char *)malloc(strlen(arg) + 1);
if (tmp == NULL)
- callback->printf_filtered(callback,"Failed to allocate buffer for logfile name \"%s\"\n",optarg);
+ sim_io_printf(sd,"Failed to allocate buffer for logfile name \"%s\"\n",optarg);
else {
strcpy(tmp,optarg);
logfile = tmp;
return SIM_RC_OK;
case 'n': /* OK */
- callback->printf_filtered(callback,"Explicit model selection not yet available (Ignoring \"%s\")\n",optarg);
+ sim_io_printf(sd,"Explicit model selection not yet available (Ignoring \"%s\")\n",optarg);
return SIM_RC_FAIL;
case 't': /* ??? */
(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);
tmp = (char *)malloc(strlen(optarg) + 1);
if (tmp == NULL)
{
- callback->printf_filtered(callback,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg);
+ sim_io_printf(sd,"Failed to allocate buffer for tracefile name \"%s\"\n",optarg);
return SIM_RC_FAIL;
}
else {
strcpy(tmp,optarg);
tracefile = tmp;
- callback->printf_filtered(callback,"Placing trace information into file \"%s\"\n",tracefile);
+ sim_io_printf(sd,"Placing trace information into file \"%s\"\n",tracefile);
}
}
#endif /* TRACE */
case 'p':
#if defined(PROFILE)
- state |= simPROFILE;
+ STATE |= simPROFILE;
return SIM_RC_OK;
#else /* !PROFILE */
fprintf(stderr,"\
case 'x':
#if defined(PROFILE)
- profile_nsamples = (unsigned)getnum(optarg);
+ profile_nsamples = (unsigned)getnum(sd, optarg);
#endif /* PROFILE */
return SIM_RC_OK;
case 'y':
#if defined(PROFILE)
- sim_set_profile((int)getnum(optarg));
+ mips_set_profile(sd, (int)getnum(sd, optarg));
#endif /* PROFILE */
return SIM_RC_OK;
'y', "FREQ", "Profile frequency",
mips_option_handler },
{ {"samples", required_argument, NULL,'x'},
- 'y', "SIZE", "Profile sample size",
+ 'x', "SIZE", "Profile sample size",
mips_option_handler },
{ {NULL, no_argument, NULL, 0}, '\0', NULL, NULL, NULL }
};
if (SR & status_IE)
{
interrupt_pending = 0;
- SignalException (Interrupt);
+ SignalExceptionInterrupt ();
}
else if (!interrupt_pending)
sim_events_schedule (sd, 1, interrupt_event, data);
/*---------------------------------------------------------------------------*/
SIM_DESC
-sim_open (kind,cb,argv)
+sim_open (kind, cb, abfd, argv)
SIM_OPEN_KIND kind;
host_callback *cb;
+ struct _bfd *abfd;
char **argv;
{
- SIM_DESC sd = &simulator;
-
- STATE_OPEN_KIND (sd) = kind;
- STATE_MAGIC (sd) = SIM_MAGIC_NUMBER;
- STATE_CALLBACK (sd) = cb;
- callback = cb;
- CPU_STATE (STATE_CPU (sd, 0)) = sd;
+ 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);
STATE_MEM_SIZE (sd) = (2 << 20);
STATE_MEM_BASE (sd) = K1BASE;
- if (callback == NULL) {
- fprintf(stderr,"SIM Error: sim_open() called without callbacks attached\n");
- return 0;
- }
-
- state = 0;
+ STATE = 0;
if (sim_pre_argv_init (sd, argv[0]) != SIM_RC_OK)
return 0;
return 0;
}
+ /* check for/establish the a reference program image */
+ if (sim_analyze_program (sd,
+ (STATE_PROG_ARGV (sd) != NULL
+ ? *STATE_PROG_ARGV (sd)
+ : NULL),
+ abfd) != SIM_RC_OK)
+ {
+ sim_module_uninstall (sd);
+ return 0;
+ }
+
+ /* Configure/verify the target byte order and other runtime
+ configuration options */
+ if (sim_config (sd) != SIM_RC_OK)
+ {
+ sim_module_uninstall (sd);
+ return 0;
+ }
+
if (sim_post_argv_init (sd) != SIM_RC_OK)
{
/* Uninstall the modules to avoid memory leaks,
/* verify assumptions the simulator made about the host type system.
This macro does not return if there is a problem */
- CHECKSIM();
+ if (sizeof(int) != (4 * sizeof(char)))
+ SignalExceptionSimulatorFault ("sizeof(int) != 4");
+ if (sizeof(word64) != (8 * sizeof(char)))
+ SignalExceptionSimulatorFault ("sizeof(word64) != 8");
#if defined(HASFPU)
/* Check that the host FPU conforms to IEEE 754-1985 for the SINGLE
int rn;
for (rn = 0; (rn < (LAST_EMBED_REGNUM + 1)); rn++) {
if (rn < 32)
- register_widths[rn] = GPRLEN;
+ cpu->register_widths[rn] = GPRLEN;
else if ((rn >= FGRIDX) && (rn < (FGRIDX + 32)))
- register_widths[rn] = GPRLEN;
+ 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++)
+ cpu->register_widths[rn] = 64;
+ /* end-sanitize-r5900 */
}
else {
logfh = fopen(logfile,"wb+");
if (logfh == NULL) {
- callback->printf_filtered(callback,"Failed to create file \"%s\", writing log information to stderr.\n",tracefile);
+ sim_io_printf(sd,"Failed to create file \"%s\", writing log information to stderr.\n",tracefile);
logfh = stderr;
}
}
would only be allocated within the "mmap" space as it is
accessed. This can also be linked to the architecture specific
support, required to simulate the MMU. */
- sim_size(STATE_MEM_SIZE (sd));
+ mips_size(sd, STATE_MEM_SIZE (sd));
/* NOTE: The above will also have enabled any profiling state! */
-
+
/* Create the monitor address space as well */
monitor = (unsigned char *)calloc(1,monitor_size);
if (!monitor)
monitor_size);
#if defined(TRACE)
- if (state & simTRACE)
- open_trace();
+ if (STATE & simTRACE)
+ open_trace(sd);
#endif /* TRACE */
+ /* Write the monitor trap address handlers into the monitor (eeprom)
+ address space. This can only be done once the target endianness
+ has been determined. */
+ {
+ unsigned loop;
+ /* Entry into the IDT monitor is via fixed address vectors, and
+ not using machine instructions. To avoid clashing with use of
+ the MIPS TRAP system, we place our own (simulator specific)
+ "undefined" instructions into the relevant vector slots. */
+ for (loop = 0; (loop < monitor_size); loop += 4) {
+ uword64 vaddr = (monitor_base + loop);
+ uword64 paddr;
+ int cca;
+ if (AddressTranslation(vaddr, isDATA, isSTORE, &paddr, &cca, isTARGET, isRAW))
+ StoreMemory(cca, AccessLength_WORD,
+ (RSVD_INSTRUCTION | (((loop >> 2) & RSVD_INSTRUCTION_ARG_MASK) << RSVD_INSTRUCTION_ARG_SHIFT)),
+ 0, paddr, vaddr, isRAW);
+ }
+ /* The PMON monitor uses the same address space, but rather than
+ branching into it the address of a routine is loaded. We can
+ cheat for the moment, and direct the PMON routine to IDT style
+ instructions within the monitor space. This relies on the IDT
+ monitor not using the locations from 0xBFC00500 onwards as its
+ entry points.*/
+ for (loop = 0; (loop < 24); loop++)
+ {
+ uword64 vaddr = (monitor_base + 0x500 + (loop * 4));
+ uword64 paddr;
+ int cca;
+ unsigned int value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */
+ switch (loop)
+ {
+ case 0: /* read */
+ value = 7;
+ break;
+
+ case 1: /* write */
+ value = 8;
+ break;
+
+ case 2: /* open */
+ value = 6;
+ break;
+
+ case 3: /* close */
+ value = 10;
+ break;
+
+ case 5: /* printf */
+ value = ((0x500 - 16) / 8); /* not an IDT reason code */
+ break;
+
+ case 8: /* cliexit */
+ value = 17;
+ break;
+
+ case 11: /* flush_cache */
+ value = 28;
+ break;
+ }
+ /* FIXME - should monitor_base be SIM_ADDR?? */
+ value = ((unsigned int)monitor_base + (value * 8));
+ if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
+ StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW);
+ else
+ sim_io_error(sd,"Failed to write to monitor space 0x%s",pr_addr(vaddr));
+
+ /* The LSI MiniRISC PMON has its vectors at 0x200, not 0x500. */
+ vaddr -= 0x300;
+ if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
+ StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW);
+ else
+ sim_io_error(sd,"Failed to write to monitor space 0x%s",pr_addr(vaddr));
+ }
+ }
+
return sd;
}
#if defined(TRACE)
static void
-open_trace()
+open_trace(sd)
+ SIM_DESC sd;
{
tracefh = fopen(tracefile,"wb+");
if (tracefh == NULL)
{
- sim_warning("Failed to create file \"%s\", writing trace information to stderr.",tracefile);
+ sim_io_eprintf(sd,"Failed to create file \"%s\", writing trace information to stderr.\n",tracefile);
tracefh = stderr;
}
}
endianness, or a method of encoding the endianness in the file
header. */
static int
-writeout32(fh,val)
+writeout32(sd,fh,val)
+ SIM_DESC sd;
FILE *fh;
unsigned int val;
{
buff[3] = ((val >> 24) & 0xFF);
}
if (fwrite(buff,4,1,fh) != 1) {
- sim_warning("Failed to write 4bytes to the profile file");
+ sim_io_eprintf(sd,"Failed to write 4bytes to the profile file\n");
res = 0;
}
return(res);
}
static int
-writeout16(fh,val)
+writeout16(sd,fh,val)
+ SIM_DESC sd;
FILE *fh;
unsigned short val;
{
buff[1] = ((val >> 8) & 0xFF);
}
if (fwrite(buff,2,1,fh) != 1) {
- sim_warning("Failed to write 2bytes to the profile file");
+ sim_io_eprintf(sd,"Failed to write 2bytes to the profile file\n");
res = 0;
}
return(res);
printf("DBG: sim_close: entered (quitting = %d)\n",quitting);
#endif
- /* Cannot assume sim_kill() has been called */
/* "quitting" is non-zero if we cannot hang on errors */
/* Ensure that any resources allocated through the callback
mechanism are released: */
- callback->shutdown(callback);
+ 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;
if (pf == NULL)
- sim_warning("Failed to open \"gmon.out\" profile file");
+ sim_io_eprintf(sd,"Failed to open \"gmon.out\" profile file\n");
else {
int ok;
#ifdef DEBUG
free(profile_hist);
profile_hist = NULL;
- state &= ~simPROFILE;
+ STATE &= ~simPROFILE;
}
#endif /* PROFILE */
if (tracefh != NULL && tracefh != stderr)
fclose(tracefh);
tracefh = NULL;
- state &= ~simTRACE;
+ STATE &= ~simTRACE;
#endif /* TRACE */
if (logfh != NULL && logfh != stdout && logfh != stderr)
/* Return the number of bytes written, or zero if error. */
#ifdef DEBUG
- callback->printf_filtered(callback,"sim_write(0x%s,buffer,%d);\n",pr_addr(addr),size);
+ sim_io_printf(sd,"sim_write(0x%s,buffer,%d);\n",pr_addr(addr),size);
#endif
/* We provide raw read and write routines, since we do not want to
/* Return the number of bytes read, or zero if error. */
#ifdef DEBUG
- callback->printf_filtered(callback,"sim_read(0x%s,buffer,%d);\n",pr_addr(addr),size);
+ sim_io_printf(sd,"sim_read(0x%s,buffer,%d);\n",pr_addr(addr),size);
#endif /* DEBUG */
/* TODO: Perform same optimisation as the sim_write() code
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
- callback->printf_filtered(callback,"sim_store_register(%d,*memory=0x%s);\n",rn,pr_addr(*((SIM_ADDR *)memory)));
+ sim_io_printf(sd,"sim_store_register(%d,*memory=0x%s);\n",rn,pr_addr(*((SIM_ADDR *)memory)));
#endif /* DEBUG */
/* Unfortunately this suffers from the same problem as the register
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)
- sim_warning("Invalid register width for %d (register store ignored)",rn);
+ 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)
+ cpu->registers1[rn - LAST_EMBED_REGNUM - 1] = T2H_8(*(uword64*)memory);
+ /* end-sanitize-r5900 */
+ else if (cpu->register_widths[rn] == 32)
+ cpu->registers[rn] = T2H_4 (*(unsigned int*)memory);
else
- {
- if (register_widths[rn] == 32)
- registers[rn] = T2H_4 (*(unsigned int*)memory);
- else
- registers[rn] = T2H_8 (*(uword64*)memory);
- }
+ cpu->registers[rn] = T2H_8 (*(uword64*)memory);
return;
}
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
- callback->printf_filtered(callback,"sim_fetch_register(%d=0x%s,mem) : place simulator registers into memory\n",rn,pr_addr(registers[rn]));
+ 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)
- sim_warning("Invalid register width for %d (register fetch ignored)",rn);
- else
- {
- if (register_widths[rn] == 32)
- *((unsigned int *)memory) = H2T_4 ((unsigned int)(registers[rn] & 0xFFFFFFFF));
- else /* 64bit register */
- *((uword64 *)memory) = H2T_8 (registers[rn]);
- }
+ 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(cpu->registers1[rn - LAST_EMBED_REGNUM - 1]);
+ /* end-sanitize-r5900 */
+ 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 (cpu->registers[rn]);
return;
}
SIM_DESC sd;
int verbose;
{
-
- return;
/* Accessed from the GDB "info files" command: */
if (STATE_VERBOSE_P (sd) || verbose)
{
}
}
-SIM_RC
-sim_load (sd,prog,abfd,from_tty)
- SIM_DESC sd;
- char *prog;
- bfd *abfd;
- int from_tty;
-{
- bfd *prog_bfd;
-
- prog_bfd = sim_load_file (sd,
- STATE_MY_NAME (sd),
- callback,
- prog,
- /* pass NULL for abfd, we always open our own */
- NULL,
- STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG);
- if (prog_bfd == NULL)
- return SIM_RC_FAIL;
- sim_analyze_program (sd, prog_bfd);
-
- /* Configure/verify the target byte order and other runtime
- configuration options */
- sim_config (sd, PREFERED_TARGET_BYTE_ORDER(prog_bfd));
-
- /* (re) Write the monitor trap address handlers into the monitor
- (eeprom) address space. This can only be done once the target
- endianness has been determined. */
- {
- unsigned loop;
- /* Entry into the IDT monitor is via fixed address vectors, and
- not using machine instructions. To avoid clashing with use of
- the MIPS TRAP system, we place our own (simulator specific)
- "undefined" instructions into the relevant vector slots. */
- for (loop = 0; (loop < monitor_size); loop += 4) {
- uword64 vaddr = (monitor_base + loop);
- uword64 paddr;
- int cca;
- if (AddressTranslation(vaddr, isDATA, isSTORE, &paddr, &cca, isTARGET, isRAW))
- StoreMemory(cca, AccessLength_WORD,
- (RSVD_INSTRUCTION | (((loop >> 2) & RSVD_INSTRUCTION_ARG_MASK) << RSVD_INSTRUCTION_ARG_SHIFT)),
- 0, paddr, vaddr, isRAW);
- }
- /* The PMON monitor uses the same address space, but rather than
- branching into it the address of a routine is loaded. We can
- cheat for the moment, and direct the PMON routine to IDT style
- instructions within the monitor space. This relies on the IDT
- monitor not using the locations from 0xBFC00500 onwards as its
- entry points.*/
- for (loop = 0; (loop < 24); loop++)
- {
- uword64 vaddr = (monitor_base + 0x500 + (loop * 4));
- uword64 paddr;
- int cca;
- unsigned int value = ((0x500 - 8) / 8); /* default UNDEFINED reason code */
- switch (loop)
- {
- case 0: /* read */
- value = 7;
- break;
-
- case 1: /* write */
- value = 8;
- break;
-
- case 2: /* open */
- value = 6;
- break;
-
- case 3: /* close */
- value = 10;
- break;
-
- case 5: /* printf */
- value = ((0x500 - 16) / 8); /* not an IDT reason code */
- break;
-
- case 8: /* cliexit */
- value = 17;
- break;
-
- case 11: /* flush_cache */
- value = 28;
- break;
- }
- /* FIXME - should monitor_base be SIM_ADDR?? */
- value = ((unsigned int)monitor_base + (value * 8));
- if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
- StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW);
- else
- sim_error("Failed to write to monitor space 0x%s",pr_addr(vaddr));
-
- /* The LSI MiniRISC PMON has its vectors at 0x200, not 0x500. */
- vaddr -= 0x300;
- if (AddressTranslation(vaddr,isDATA,isSTORE,&paddr,&cca,isTARGET,isRAW))
- StoreMemory(cca,AccessLength_WORD,value,0,paddr,vaddr,isRAW);
- else
- sim_error("Failed to write to monitor space 0x%s",pr_addr(vaddr));
- }
- }
-
- return SIM_RC_OK;
-}
SIM_RC
-sim_create_inferior (sd, argv,env)
+sim_create_inferior (sd, abfd, argv,env)
SIM_DESC sd;
+ struct _bfd *abfd;
char **argv;
char **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
patterns (e.g. simulating ROM monitors). */
#if 1
- PC = (uword64) STATE_START_ADDR(sd);
+ if (abfd != NULL)
+ PC = (unsigned64) bfd_get_start_address(abfd);
+ else
+ PC = 0; /* ???? */
#else
/* TODO: Sort this properly. SIM_ADDR may already be a 64bit value: */
- PC = SIGNEXTEND(bfd_get_start_address(prog_bfd),32);
+ PC = SIGNEXTEND(bfd_get_start_address(abfd),32);
#endif
/* Prepare to execute the program to be simulated */
if (argv || env) {
#if 0 /* def DEBUG */
- callback->printf_filtered(callback,"sim_create_inferior() : passed arguments ignored\n");
+ sim_io_printf(sd,"sim_create_inferior() : passed arguments ignored\n");
{
char **cptr;
for (cptr = argv; (cptr && *cptr); cptr++)
return SIM_RC_OK;
}
-void
-sim_kill (sd)
- SIM_DESC sd;
-{
-#if 1
- /* This routine should be for terminating any existing simulation
- thread. Since we are single-threaded only at the moment, this is
- not an issue. It should *NOT* be used to terminate the
- simulator. */
-#else /* do *NOT* call sim_close */
- sim_close(sd, 1); /* Do not hang on errors */
- /* This would also be the point where any memory mapped areas used
- by the simulator should be released. */
-#endif
- return;
-}
-
typedef enum {e_terminate,e_help,e_setmemsize,e_reset} e_cmds;
static struct t_sim_command {
{
struct t_sim_command *cptr;
- if (callback == NULL) {
- fprintf(stderr,"Simulator not enabled: \"target sim\" should be used to activate\n");
- return;
- }
-
if (!(cmd && *cmd != '\0'))
cmd = "help";
case e_help: /* no arguments */
{ /* no arguments */
struct t_sim_command *lptr;
- callback->printf_filtered(callback,"List of MIPS simulator commands:\n");
+ sim_io_printf(sd,"List of MIPS simulator commands:\n");
for (lptr = sim_commands; lptr->name; lptr++)
- callback->printf_filtered(callback,"%s %s\n",lptr->name,lptr->help);
+ sim_io_printf(sd,"%s %s\n",lptr->name,lptr->help);
sim_args_command (sd, "help");
}
break;
case e_setmemsize: /* memory size argument */
{
- unsigned int newsize = (unsigned int)getnum(cmd);
- sim_size(newsize);
+ unsigned int newsize = (unsigned int)getnum(sd, cmd);
+ mips_size(sd, newsize);
}
break;
case e_reset: /* no arguments */
- ColdReset();
+ ColdReset(sd);
/* NOTE: See the comments in sim_open() relating to device
initialisation. */
break;
default:
- callback->printf_filtered(callback,"FATAL: Matched \"%s\", but failed to match command id %d.\n",cmd,cptr->id);
+ sim_io_printf(sd,"FATAL: Matched \"%s\", but failed to match command id %d.\n",cmd,cptr->id);
break;
}
break;
{
/* try for a common command when the sim specific lookup fails */
if (sim_args_command (sd, cmd) != SIM_RC_OK)
- callback->printf_filtered(callback,"Error: \"%s\" is not a valid MIPS simulator command.\n",cmd);
+ sim_io_printf(sd,"Error: \"%s\" is not a valid MIPS simulator command.\n",cmd);
}
return;
/* The profiling format is described in the "gmon_out.h" header file */
-void
-sim_set_profile (n)
+static void
+mips_set_profile (sd,n)
+ SIM_DESC sd;
int n;
{
#if defined(PROFILE)
profile_frequency = n;
- state |= simPROFILE;
+ STATE |= simPROFILE;
#endif /* PROFILE */
return;
}
-void
-sim_set_profile_size (n)
+static void
+mips_set_profile_size (sd,n)
+ SIM_DESC sd;
int n;
{
- SIM_DESC sd = &simulator;
#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: */
else
profile_hist = (unsigned short *)realloc(profile_hist,bsize);
if (profile_hist == NULL) {
- sim_warning("Failed to allocate VM for profiling buffer (0x%08X bytes)",bsize);
- state &= ~simPROFILE;
+ sim_io_eprintf(sd,"Failed to allocate VM for profiling buffer (0x%08X bytes)\n",bsize);
+ STATE &= ~simPROFILE;
}
}
#endif /* PROFILE */
return;
}
-void
-sim_size(newsize)
+static void
+mips_size(sd, newsize)
+ SIM_DESC sd;
int newsize;
{
- SIM_DESC sd = &simulator;
char *new;
/* Used by "run", and internally, to set the simulated memory size */
if (newsize == 0) {
- callback->printf_filtered(callback,"Zero not valid: Memory size still 0x%08X bytes\n",STATE_MEM_SIZE (sd));
+ sim_io_printf(sd,"Zero not valid: Memory size still 0x%08X bytes\n",STATE_MEM_SIZE (sd));
return;
}
newsize = power2(newsize);
new = (char *)realloc(STATE_MEMORY (sd),newsize);
if (new == NULL) {
if (STATE_MEMORY (sd) == NULL)
- sim_error("Not enough VM for simulation memory of 0x%08X bytes",STATE_MEM_SIZE (sd));
+ sim_io_error(sd,"Not enough VM for simulation memory of 0x%08X bytes",STATE_MEM_SIZE (sd));
else
- sim_warning("Failed to resize memory (still 0x%08X bytes)",STATE_MEM_SIZE (sd));
+ sim_io_eprintf(sd,"Failed to resize memory (still 0x%08X bytes)\n",STATE_MEM_SIZE (sd));
} else {
STATE_MEM_SIZE (sd) = (unsigned)newsize;
STATE_MEMORY (sd) = new;
#if defined(PROFILE)
/* Ensure that we sample across the new memory range */
- sim_set_profile_size(profile_nsamples);
+ mips_set_profile_size(sd, profile_nsamples);
#endif /* PROFILE */
}
return;
}
-int
-sim_trace(sd)
- SIM_DESC sd;
-{
- sim_io_eprintf (sd, "Sim trace not supported");
-#if 0
- /* This routine is called by the "run" program, when detailed
- execution information is required. Rather than executing a single
- instruction, and looping around externally... we just start
- simulating, returning TRUE when the simulator stops (for whatever
- reason). */
-
-#if defined(TRACE)
- /* Ensure tracing is enabled, if available */
- if (tracefh == NULL)
- {
- open_trace();
- state |= simTRACE;
- }
-#endif /* TRACE */
-
-#if 0
- state &= ~(simSTOP | simSTEP); /* execute until event */
-#endif
- state |= (simHALTEX | simHALTIN); /* treat interrupt event as exception */
- /* Start executing instructions from the current state (set
- explicitly by register updates, or by sim_create_inferior): */
- simulate();
-
-#endif
- return(1);
-}
/*---------------------------------------------------------------------------*/
/*-- Private simulator support interface ------------------------------------*/
/* Simple monitor interface (currently setup for the IDT and PMON monitors) */
static void
-sim_monitor(reason)
+sim_monitor(sd,reason)
+ SIM_DESC sd;
unsigned int reason;
{
- SIM_DESC sd = &simulator;
#ifdef DEBUG
printf("DBG: sim_monitor: entered (reason = %d)\n",reason);
#endif /* DEBUG */
uword64 paddr;
int cca;
if (AddressTranslation(A0,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL))
- V0 = callback->open(callback,(char *)((int)paddr),(int)A1);
+ V0 = sim_io_open(sd,(char *)((int)paddr),(int)A1);
else
- sim_error("Attempt to pass pointer that does not reference simulated memory");
+ sim_io_error(sd,"Attempt to pass pointer that does not reference simulated memory");
}
break;
uword64 paddr;
int cca;
if (AddressTranslation(A1,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL))
- V0 = callback->read(callback,(int)A0,(char *)((int)paddr),(int)A2);
+ V0 = sim_io_read(sd,(int)A0,(char *)((int)paddr),(int)A2);
else
- sim_error("Attempt to pass pointer that does not reference simulated memory");
+ sim_io_error(sd,"Attempt to pass pointer that does not reference simulated memory");
}
break;
uword64 paddr;
int cca;
if (AddressTranslation(A1,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL))
- V0 = callback->write(callback,(int)A0,(const char *)((int)paddr),(int)A2);
+ V0 = sim_io_write(sd,(int)A0,(const char *)((int)paddr),(int)A2);
else
- sim_error("Attempt to pass pointer that does not reference simulated memory");
+ sim_io_error(sd,"Attempt to pass pointer that does not reference simulated memory");
}
break;
case 10: /* int close(int file) */
- V0 = callback->close(callback,(int)A0);
+ V0 = sim_io_close(sd,(int)A0);
break;
case 11: /* char inbyte(void) */
{
char tmp;
- if (callback->read_stdin(callback,&tmp,sizeof(char)) != sizeof(char)) {
- sim_error("Invalid return from character read");
+ if (sim_io_read_stdin(sd,&tmp,sizeof(char)) != sizeof(char)) {
+ sim_io_error(sd,"Invalid return from character read");
V0 = (ut_reg)-1;
}
else
case 12: /* void outbyte(char chr) : write a byte to "stdout" */
{
char tmp = (char)(A0 & 0xFF);
- callback->write_stdout(callback,&tmp,sizeof(char));
+ sim_io_write_stdout(sd,&tmp,sizeof(char));
}
break;
case 17: /* void _exit() */
- sim_warning("sim_monitor(17): _exit(int reason) to be coded");
+ sim_io_eprintf(sd,"sim_monitor(17): _exit(int reason) to be coded\n");
sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA, sim_exited,
(unsigned int)(A0 & 0xFFFFFFFF));
break;
failed = -1;
if (failed)
- sim_error("Invalid pointer passed into monitor call");
+ sim_io_error(sd,"Invalid pointer passed into monitor call");
}
break;
haddot = 1;
}
if (*s == '%') {
- callback->printf_filtered(callback,"%%");
+ sim_io_printf(sd,"%%");
} else if (*s == 's') {
if ((int)*ap != 0) {
if (AddressTranslation(*ap++,isDATA,isLOAD,&paddr,&cca,isHOST,isREAL)) {
char *p = (char *)((int)paddr);;
- callback->printf_filtered(callback,p);
+ sim_io_printf(sd,p);
} else {
ap++;
- sim_error("Attempt to pass pointer that does not reference simulated memory");
+ sim_io_error(sd,"Attempt to pass pointer that does not reference simulated memory");
}
}
else
- callback->printf_filtered(callback,"(null)");
+ sim_io_printf(sd,"(null)");
} else if (*s == 'c') {
int n = (int)*ap++;
- callback->printf_filtered(callback,"%c",n);
+ sim_io_printf(sd,"%c",n);
} else {
if (*s == 'l') {
if (*++s == 'l') {
if (strchr ("dobxXu", *s)) {
word64 lv = (word64) *ap++;
if (*s == 'b')
- callback->printf_filtered(callback,"<binary not supported>");
+ sim_io_printf(sd,"<binary not supported>");
else {
sprintf(tmp,"%%%s%c",longlong ? "ll" : "",*s);
if (longlong)
- callback->printf_filtered(callback,tmp,lv);
+ sim_io_printf(sd,tmp,lv);
else
- callback->printf_filtered(callback,tmp,(int)lv);
+ sim_io_printf(sd,tmp,(int)lv);
}
} else if (strchr ("eEfgG", *s)) {
#ifdef _MSC_VER /* MSVC version 2.x can't convert from uword64 directly */
double dbl = (double)*ap++;
#endif
sprintf(tmp,"%%%d.%d%c",width,trunc,*s);
- callback->printf_filtered(callback,tmp,dbl);
+ sim_io_printf(sd,tmp,dbl);
trunc = 0;
}
}
s++;
} else
- callback->printf_filtered(callback,"%c",*s++);
+ sim_io_printf(sd,"%c",*s++);
}
} else
- sim_error("Attempt to pass pointer that does not reference simulated memory");
+ sim_io_error(sd,"Attempt to pass pointer that does not reference simulated memory");
}
break;
default:
- sim_warning("TODO: sim_monitor(%d) : PC = 0x%s",reason,pr_addr(IPC));
- sim_warning("(Arguments : A0 = 0x%s : A1 = 0x%s : A2 = 0x%s : A3 = 0x%s)",pr_addr(A0),pr_addr(A1),pr_addr(A2),pr_addr(A3));
+ sim_io_eprintf(sd,"TODO: sim_monitor(%d) : PC = 0x%s\n",reason,pr_addr(IPC));
+ sim_io_eprintf(sd,"(Arguments : A0 = 0x%s : A1 = 0x%s : A2 = 0x%s : A3 = 0x%s)\n",pr_addr(A0),pr_addr(A1),pr_addr(A2),pr_addr(A3));
break;
}
return;
/* Store a word into memory. */
static void
-store_word (vaddr, val)
+store_word (sd, vaddr, val)
+ SIM_DESC sd;
uword64 vaddr;
t_reg val;
{
int uncached;
if ((vaddr & 3) != 0)
- SignalException (AddressStore);
+ SignalExceptionAddressStore ();
else
{
if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
/* Load a word from memory. */
static t_reg
-load_word (vaddr)
+load_word (sd, vaddr)
+ SIM_DESC sd;
uword64 vaddr;
{
if ((vaddr & 3) != 0)
- SignalException (AddressLoad);
+ SignalExceptionAddressLoad ();
else
{
uword64 paddr;
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;
/* 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;
for (i = 0; i < sregs; i++)
{
tsp -= 4;
- store_word ((uword64) tsp, registers[16 + i]);
+ store_word ((uword64) tsp, GPR[16 + i]);
}
}
else
for (i = 0; i < sregs; i++)
{
tsp -= 4;
- registers[i + 16] = load_word ((uword64) tsp);
+ GPR[i + 16] = load_word ((uword64) tsp);
}
SP += 32;
+#if defined(HASFPU)
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) */
PC = RA;
}
}
-void
-sim_warning(char *fmt,...)
-{
- char buf[256];
- va_list ap;
-
- va_start (ap,fmt);
- vsprintf (buf, fmt, ap);
- va_end (ap);
-
- if (logfh != NULL) {
- fprintf(logfh,"SIM Warning: %s\n", buf);
- } else {
- callback->printf_filtered(callback,"SIM Warning: %s\n", buf);
- }
- /* This used to call SignalException with a SimulatorFault, but that causes
- the simulator to exit, and that is inappropriate for a warning. */
- return;
-}
-
-void
-sim_error(char *fmt,...)
-{
- char buf[256];
- va_list ap;
-
- va_start (ap,fmt);
- vsprintf (buf, fmt, ap);
- va_end (ap);
-
- callback->printf_filtered(callback,"SIM Error: %s", buf);
- SignalException (SimulatorFault, buf);
- return;
-}
-
static unsigned int
power2(value)
unsigned int value;
}
static long
-getnum(value)
+getnum(sd,value)
+ SIM_DESC sd;
char *value;
{
long num;
num = strtol(value,&end,10);
if (end == value)
- callback->printf_filtered(callback,"Warning: Invalid number \"%s\" ignored, using zero\n",value);
+ sim_io_printf(sd,"Warning: Invalid number \"%s\" ignored, using zero\n",value);
else {
if (*end && ((tolower(*end) == 'k') || (tolower(*end) == 'm'))) {
if (tolower(*end) == 'k')
end++;
}
if (*end)
- callback->printf_filtered(callback,"Warning: Spurious characters \"%s\" at end of number ignored\n",end);
+ sim_io_printf(sd,"Warning: Spurious characters \"%s\" at end of number ignored\n",end);
}
return(num);
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,
/*---------------------------------------------------------------------------*/
static void
-ColdReset()
+ColdReset(sd)
+ SIM_DESC sd;
{
/* RESET: Fixed PC address: */
PC = (((uword64)0xFFFFFFFF<<32) | 0xBFC00000);
{
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)
{
int rn;
for (rn = 0; (rn < 32); rn++)
- fpr_state[rn] = fmt_uninterpreted;
+ FPR_STATE[rn] = fmt_uninterpreted;
}
#endif /* HASFPU */
along with the exception generation is used to notify whether a
valid address translation occured */
-static int
-AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw)
+int
+address_translation(sd,vAddr,IorD,LorS,pAddr,CCA,host,raw)
+ SIM_DESC sd;
uword64 vAddr;
int IorD;
int LorS;
int host;
int raw;
{
- SIM_DESC sd = &simulator;
int res = -1; /* TRUE : Assume good return */
#ifdef DEBUG
- callback->printf_filtered(callback,"AddressTranslation(0x%s,%s,%s,...);\n",pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "iSTORE" : "isLOAD"));
+ sim_io_printf(sd,"AddressTranslation(0x%s,%s,%s,...);\n",pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "iSTORE" : "isLOAD"));
#endif
/* Check that the address is valid for this memory model */
*pAddr = (int)&monitor[((unsigned int)(vAddr - monitor_base) & (monitor_size - 1))];
} else {
#ifdef DEBUG
- sim_warning("Failed: AddressTranslation(0x%s,%s,%s,...) IPC = 0x%s",pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "isSTORE" : "isLOAD"),pr_addr(IPC));
+ sim_io_eprintf(sd,"Failed: AddressTranslation(0x%s,%s,%s,...) IPC = 0x%s\n",pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(LorS ? "isSTORE" : "isLOAD"),pr_addr(IPC));
#endif /* DEBUG */
res = 0; /* AddressTranslation has failed */
*pAddr = (SIM_ADDR)-1;
if (!raw) /* only generate exceptions on real memory transfers */
- SignalException((LorS == isSTORE) ? AddressStore : AddressLoad);
+ if (LorS == isSTORE)
+ SignalExceptionAddressStore ();
+ else
+ SignalExceptionAddressLoad ();
#ifdef DEBUG
else
/* This is a normal occurance during gdb operation, for instance trying
to print parameters at function start before they have been setup,
and hence we should not print a warning except when debugging the
simulator. */
- sim_warning("AddressTranslation for %s %s from 0x%s failed",(IorD ? "data" : "instruction"),(LorS ? "store" : "load"),pr_addr(vAddr));
+ sim_io_eprintf(sd,"AddressTranslation for %s %s from 0x%s failed\n",(IorD ? "data" : "instruction"),(LorS ? "store" : "load"),pr_addr(vAddr));
#endif
}
int hint;
{
#ifdef DEBUG
- callback->printf_filtered(callback,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint);
+ sim_io_printf(sd,"Prefetch(%d,0x%s,0x%s,%d,%d);\n",CCA,pr_addr(pAddr),pr_addr(vAddr),DATA,hint);
#endif /* DEBUG */
/* For our simple memory model we do nothing */
alignment block of memory is read and loaded into the cache to
satisfy a load reference. At a minimum, the block is the entire
memory element. */
-static void
-LoadMemory(memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw)
+void
+load_memory(sd,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw)
+ SIM_DESC sd;
uword64* memvalp;
uword64* memval1p;
int CCA;
int IorD;
int raw;
{
- SIM_DESC sd = &simulator;
uword64 value = 0;
uword64 value1 = 0;
#ifdef DEBUG
if (STATE_MEMORY (sd) == NULL)
- callback->printf_filtered(callback,"DBG: LoadMemory(%p,%p,%d,%d,0x%s,0x%s,%s,%s)\n",memvalp,memval1p,CCA,AccessLength,pr_addr(pAddr),pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(raw ? "isRAW" : "isREAL"));
+ sim_io_printf(sd,"DBG: LoadMemory(%p,%p,%d,%d,0x%s,0x%s,%s,%s)\n",memvalp,memval1p,CCA,AccessLength,pr_addr(pAddr),pr_addr(vAddr),(IorD ? "isDATA" : "isINSTRUCTION"),(raw ? "isRAW" : "isREAL"));
#endif /* DEBUG */
#if defined(WARN_MEM)
if (CCA != uncached)
- sim_warning("LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)",CCA);
+ sim_io_eprintf(sd,"LoadMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK) {
/* In reality this should be a Bus Error */
- sim_error("AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",AccessLength,(LOADDRMASK + 1)<<2,pr_addr(pAddr));
+ sim_io_error(sd,"AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",AccessLength,(LOADDRMASK + 1)<<2,pr_addr(pAddr));
}
#endif /* WARN_MEM */
if ((IorD == isINSTRUCTION)
&& ((pAddr & 0x3) != 0)
&& (((pAddr & 0x1) != 0) || ((vAddr & 0x1) == 0)))
- SignalException(InstructionFetch);
+ SignalExceptionInstructionFetch ();
else {
unsigned int index = 0;
unsigned char *mem = NULL;
#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
mem = monitor;
}
if (mem == NULL)
- sim_error("Simulator memory not found for physical address 0x%s\n",pr_addr(pAddr));
+ sim_io_error(sd,"Simulator memory not found for physical address 0x%s\n",pr_addr(pAddr));
else {
/* If we obtained the endianness of the host, and it is the same
as the target memory system we can optimise the memory
MemElem data should actually be stored; only these bytes in memory
will be changed. */
-static void
-StoreMemory(CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw)
+void
+store_memory(sd,CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw)
+ SIM_DESC sd;
int CCA;
int AccessLength;
uword64 MemElem;
uword64 vAddr;
int raw;
{
- SIM_DESC sd = &simulator;
#ifdef DEBUG
- callback->printf_filtered(callback,"DBG: StoreMemory(%d,%d,0x%s,0x%s,0x%s,0x%s,%s)\n",CCA,AccessLength,pr_uword64(MemElem),pr_uword64(MemElem1),pr_addr(pAddr),pr_addr(vAddr),(raw ? "isRAW" : "isREAL"));
+ sim_io_printf(sd,"DBG: StoreMemory(%d,%d,0x%s,0x%s,0x%s,0x%s,%s)\n",CCA,AccessLength,pr_uword64(MemElem),pr_uword64(MemElem1),pr_addr(pAddr),pr_addr(vAddr),(raw ? "isRAW" : "isREAL"));
#endif /* DEBUG */
#if defined(WARN_MEM)
if (CCA != uncached)
- sim_warning("StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)",CCA);
+ sim_io_eprintf(sd,"StoreMemory CCA (%d) is not uncached (currently all accesses treated as cached)\n",CCA);
if (((pAddr & LOADDRMASK) + AccessLength) > LOADDRMASK)
- sim_error("AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",AccessLength,(LOADDRMASK + 1)<<2,pr_addr(pAddr));
+ sim_io_error(sd,"AccessLength of %d would extend over %dbit aligned boundary for physical address 0x%s\n",AccessLength,(LOADDRMASK + 1)<<2,pr_addr(pAddr));
#endif /* WARN_MEM */
#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
}
if (mem == NULL)
- sim_error("Simulator memory not found for physical address 0x%s\n",pr_addr(pAddr));
+ sim_io_error(sd,"Simulator memory not found for physical address 0x%s\n",pr_addr(pAddr));
else {
int shift = 0;
int stype;
{
#ifdef DEBUG
- callback->printf_filtered(callback,"SyncOperation(%d) : TODO\n",stype);
+ sim_io_printf(sd,"SyncOperation(%d) : TODO\n",stype);
#endif /* DEBUG */
return;
}
that aborts the instruction. The instruction operation pseudocode
will never see a return from this function call. */
-static void
-SignalException (int exception,...)
+void
+signal_exception (SIM_DESC sd, int exception,...)
{
int vector;
- SIM_DESC sd = &simulator;
+
+#ifdef DEBUG
+ sim_io_printf(sd,"DBG: SignalException(%d) IPC = 0x%s\n",exception,pr_addr(IPC));
+#endif /* DEBUG */
+
/* Ensure that any active atomic read/modify/write operation will fail: */
LLBIT = 0;
switch (exception) {
/* TODO: For testing purposes I have been ignoring TRAPs. In
reality we should either simulate them, or allow the user to
- ignore them at run-time. */
+ ignore them at run-time.
+ Same for SYSCALL */
case Trap :
- sim_warning("Ignoring instruction TRAP (PC 0x%s)",pr_addr(IPC));
+ sim_io_eprintf(sd,"Ignoring instruction TRAP (PC 0x%s)\n",pr_addr(IPC));
break;
+ case SystemCall :
+ {
+ va_list ap;
+ unsigned int instruction;
+ unsigned int code;
+
+ va_start(ap,exception);
+ instruction = va_arg(ap,unsigned int);
+ va_end(ap);
+
+ code = (instruction >> 6) & 0xFFFFF;
+
+ sim_io_eprintf(sd,"Ignoring instruction `syscall %d' (PC 0x%s)\n",
+ code, pr_addr(IPC));
+ }
+ break;
+
+ case DebugBreakPoint :
+ if (! (Debug & Debug_DM))
+ {
+ if (INDELAYSLOT())
+ {
+ CANCELDELAYSLOT();
+
+ Debug |= Debug_DBD; /* signaled from within in delay slot */
+ DEPC = IPC - 4; /* reference the branch instruction */
+ }
+ else
+ {
+ Debug &= ~Debug_DBD; /* not signaled from within a delay slot */
+ DEPC = IPC;
+ }
+
+ Debug |= Debug_DM; /* in debugging mode */
+ Debug |= Debug_DBp; /* raising a DBp exception */
+ PC = 0xBFC00200;
+ sim_engine_restart (sd, STATE_CPU (sd, 0), NULL, NULL_CIA);
+ }
+ break;
+
case ReservedInstruction :
{
va_list ap;
actual trap instructions are used, we would not need to
perform this magic. */
if ((instruction & RSVD_INSTRUCTION_MASK) == RSVD_INSTRUCTION) {
- sim_monitor( ((instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK) );
+ sim_monitor(sd, ((instruction >> RSVD_INSTRUCTION_ARG_SHIFT) & RSVD_INSTRUCTION_ARG_MASK) );
PC = RA; /* simulate the return from the vector entry */
/* NOTE: This assumes that a branch-and-link style
instruction was used to enter the vector (which is the
mips16_entry (instruction);
sim_engine_restart (sd, STATE_CPU (sd, 0), NULL, NULL_CIA);
} /* else fall through to normal exception processing */
- sim_warning("ReservedInstruction 0x%08X at IPC = 0x%s",instruction,pr_addr(IPC));
+ sim_io_eprintf(sd,"ReservedInstruction 0x%08X at IPC = 0x%s\n",instruction,pr_addr(IPC));
}
- default:
+ case BreakPoint:
#ifdef DEBUG
- if (exception != BreakPoint)
- callback->printf_filtered(callback,"DBG: SignalException(%d) IPC = 0x%s\n",exception,pr_addr(IPC));
+ sim_io_printf(sd,"DBG: SignalException(%d) IPC = 0x%s\n",exception,pr_addr(IPC));
#endif /* DEBUG */
+ /* Keep a copy of the current A0 in-case this is the program exit
+ breakpoint: */
+ {
+ va_list ap;
+ unsigned int instruction;
+ va_start(ap,exception);
+ instruction = va_arg(ap,unsigned int);
+ va_end(ap);
+ /* Check for our special terminating BREAK: */
+ if ((instruction & 0x03FFFFC0) == 0x03ff0000) {
+ sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
+ sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));
+ }
+ }
+ if (STATE & simDELAYSLOT)
+ PC = IPC - 4; /* reference the branch instruction */
+ else
+ PC = IPC;
+ sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
+ sim_stopped, SIGTRAP);
+
+ default:
/* Store exception code into current exception id variable (used
by exit code): */
/* TODO: If not simulating exceptions then stop the simulator
execution. At the moment we always stop the simulation. */
- /* state |= (simSTOP | simEXCEPTION); */
-
- /* Keep a copy of the current A0 in-case this is the program exit
- breakpoint: */
- if (exception == BreakPoint) {
- va_list ap;
- unsigned int instruction;
- va_start(ap,exception);
- instruction = va_arg(ap,unsigned int);
- va_end(ap);
- /* Check for our special terminating BREAK: */
- if ((instruction & 0x03FFFFC0) == 0x03ff0000) {
- sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
- sim_exited, (unsigned int)(A0 & 0xFFFFFFFF));
- }
- }
/* See figure 5-17 for an outline of the code below */
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 */
}
}
else
{
- CAUSE = 0;
+ CAUSE = (exception << 2);
vector = 0x180;
}
SR |= status_EXL;
case Trap:
case Watch:
case SystemCall:
- case BreakPoint:
PC = EPC;
sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
sim_stopped, SIGTRAP);
+ case BreakPoint:
+ PC = EPC;
+ sim_engine_abort (sd, STATE_CPU (sd, 0), NULL_CIA,
+ "FATAL: Should not encounter a breakpoint\n");
+
default : /* Unknown internal exception */
PC = EPC;
sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
static void
UndefinedResult()
{
- sim_warning("UndefinedResult: IPC = 0x%s",pr_addr(IPC));
+ sim_io_eprintf(sd,"UndefinedResult: IPC = 0x%s\n",pr_addr(IPC));
#if 0 /* Disabled for the moment, since it actually happens a lot at the moment. */
state |= simSTOP;
#endif
}
#endif /* WARN_RESULT */
-static void UNUSED
-CacheOp(op,pAddr,vAddr,instruction)
+void
+cache_op(sd,op,pAddr,vAddr,instruction)
+ SIM_DESC sd;
int op;
uword64 pAddr;
uword64 vAddr;
enable bit in the Status Register is clear - a coprocessor
unusable exception is taken. */
#if 0
- callback->printf_filtered(callback,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(IPC));
+ sim_io_printf(sd,"TODO: Cache availability checking (PC = 0x%s)\n",pr_addr(IPC));
#endif
switch (op & 0x3) {
case 6: /* Hit Writeback */
if (!icache_warning)
{
- sim_warning("Instruction CACHE operation %d to be coded",(op >> 2));
+ sim_io_eprintf(sd,"Instruction CACHE operation %d to be coded\n",(op >> 2));
icache_warning = 1;
}
break;
case 6: /* Hit Writeback */
if (!dcache_warning)
{
- sim_warning("Data CACHE operation %d to be coded",(op >> 2));
+ sim_io_eprintf(sd,"Data CACHE operation %d to be coded\n",(op >> 2));
dcache_warning = 1;
}
break;
#define DOFMT(v) (((v) == fmt_single) ? "single" : (((v) == fmt_double) ? "double" : (((v) == fmt_word) ? "word" : (((v) == fmt_long) ? "long" : (((v) == fmt_unknown) ? "<unknown>" : (((v) == fmt_uninterpreted) ? "<uninterpreted>" : "<format error>"))))))
#endif /* DEBUG */
-static uword64
-ValueFPR(fpr,fmt)
- int fpr;
- FP_formats fmt;
+uword64
+value_fpr(sd,fpr,fmt)
+ SIM_DESC sd;
+ int fpr;
+ FP_formats fmt;
{
uword64 value = 0;
int err = 0;
#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_warning("FPR %d (format %s) being accessed with format %s - setting to unknown (PC = 0x%s)",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:
if ((fpr & 1) == 0) { /* even registers only */
value = ((((uword64)FGR[fpr+1]) << 32) | (FGR[fpr] & 0xFFFFFFFF));
} else {
- SignalException (ReservedInstruction, 0);
+ SignalException(ReservedInstruction,0);
}
break;
}
if (err)
- SignalException(SimulatorFault,"Unrecognised FP format in ValueFPR()");
+ SignalExceptionSimulatorFault ("Unrecognised FP format in ValueFPR()");
#ifdef DEBUG
printf("DBG: ValueFPR: fpr = %d, fmt = %s, value = 0x%s : PC = 0x%s : SizeFGR() = %d\n",fpr,DOFMT(fmt),pr_addr(value),pr_addr(IPC),SizeFGR());
return(value);
}
-static void
-StoreFPR(fpr,fmt,value)
+void
+store_fpr(sd,fpr,fmt,value)
+ SIM_DESC sd;
int fpr;
FP_formats fmt;
uword64 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;
}
case fmt_single :
case fmt_word :
FGR[fpr] = (value & 0xFFFFFFFF);
- fpr_state[fpr] = fmt;
+ FPR_STATE[fpr] = fmt;
break;
case fmt_uninterpreted:
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;
- SignalException (ReservedInstruction, 0);
+ 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;
}
#endif /* WARN_RESULT */
if (err)
- SignalException(SimulatorFault,"Unrecognised FP format in StoreFPR()");
+ SignalExceptionSimulatorFault ("Unrecognised FP format in StoreFPR()");
#ifdef DEBUG
printf("DBG: StoreFPR: fpr[%d] = 0x%s (format %s)\n",fpr,pr_addr(FGR[fpr]),DOFMT(fmt));
return;
}
-static int
+int
NaN(op,fmt)
uword64 op;
FP_formats fmt;
return(boolean);
}
-static int
+int
Infinity(op,fmt)
uword64 op;
FP_formats fmt;
return(boolean);
}
-static int
+int
Less(op1,op2,fmt)
uword64 op1;
uword64 op2;
return(boolean);
}
-static int
+int
Equal(op1,op2,fmt)
uword64 op1;
uword64 op2;
return(boolean);
}
-static uword64
+uword64
AbsoluteValue(op,fmt)
uword64 op;
FP_formats fmt;
return(result);
}
-static uword64
+uword64
Negate(op,fmt)
uword64 op;
FP_formats fmt;
return(result);
}
-static uword64
+uword64
Add(op1,op2,fmt)
uword64 op1;
uword64 op2;
return(result);
}
-static uword64
+uword64
Sub(op1,op2,fmt)
uword64 op1;
uword64 op2;
return(result);
}
-static uword64
+uword64
Multiply(op1,op2,fmt)
uword64 op1;
uword64 op2;
return(result);
}
-static uword64
+uword64
Divide(op1,op2,fmt)
uword64 op1;
uword64 op2;
return(result);
}
-static uword64 UNUSED
+uword64 UNUSED
Recip(op,fmt)
uword64 op;
FP_formats fmt;
return(result);
}
-static uword64
+uword64
SquareRoot(op,fmt)
uword64 op;
FP_formats fmt;
return(result);
}
-static uword64
-Convert(rm,op,from,to)
+uword64
+convert(sd,rm,op,from,to)
+ SIM_DESC sd;
int rm;
uword64 op;
FP_formats from;
case fmt_long:
if (Infinity(op,from) || NaN(op,from) || (1 == 0/*TODO: check range */)) {
printf("DBG: TODO: update FCSR\n");
- SignalException(FPE);
+ SignalExceptionFPE ();
} else {
if (to == fmt_word) {
int tmp = 0;
return(0);
}
-static void
-COP_LW(coproc_num,coproc_reg,memword)
+void
+cop_lw(sd,coproc_num,coproc_reg,memword)
+ SIM_DESC sd;
int coproc_num, coproc_reg;
unsigned int 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 */
default:
#if 0 /* this should be controlled by a configuration option */
- callback->printf_filtered(callback,"COP_LW(%d,%d,0x%08X) at IPC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,memword,pr_addr(IPC));
+ sim_io_printf(sd,"COP_LW(%d,%d,0x%08X) at IPC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,memword,pr_addr(IPC));
#endif
break;
}
return;
}
-static void
-COP_LD(coproc_num,coproc_reg,memword)
+void
+cop_ld(sd,coproc_num,coproc_reg,memword)
+ SIM_DESC sd;
int coproc_num, coproc_reg;
uword64 memword;
{
default:
#if 0 /* this message should be controlled by a configuration option */
- callback->printf_filtered(callback,"COP_LD(%d,%d,0x%s) at IPC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(memword),pr_addr(IPC));
+ sim_io_printf(sd,"COP_LD(%d,%d,0x%s) at IPC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(memword),pr_addr(IPC));
#endif
break;
}
return;
}
-static unsigned int
-COP_SW(coproc_num,coproc_reg)
+unsigned int
+cop_sw(sd,coproc_num,coproc_reg)
+ SIM_DESC sd;
int coproc_num, coproc_reg;
{
unsigned int value = 0;
- FP_formats hold;
switch (coproc_num) {
#if defined(HASFPU)
case 1:
#if 1
- hold = fpr_state[coproc_reg];
- fpr_state[coproc_reg] = fmt_word;
- value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted);
- fpr_state[coproc_reg] = hold;
+ {
+ FP_formats hold;
+ hold = FPR_STATE[coproc_reg];
+ FPR_STATE[coproc_reg] = fmt_word;
+ value = (unsigned int)ValueFPR(coproc_reg,fmt_uninterpreted);
+ 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
default:
#if 0 /* should be controlled by configuration option */
- callback->printf_filtered(callback,"COP_SW(%d,%d) at IPC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(IPC));
+ sim_io_printf(sd,"COP_SW(%d,%d) at IPC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(IPC));
#endif
break;
}
return(value);
}
-static uword64
-COP_SD(coproc_num,coproc_reg)
+uword64
+cop_sd(sd,coproc_num,coproc_reg)
+ SIM_DESC sd;
int coproc_num, coproc_reg;
{
uword64 value = 0;
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
default:
#if 0 /* should be controlled by configuration option */
- callback->printf_filtered(callback,"COP_SD(%d,%d) at IPC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(IPC));
+ sim_io_printf(sd,"COP_SD(%d,%d) at IPC = 0x%s : TODO (architecture specific)\n",coproc_num,coproc_reg,pr_addr(IPC));
#endif
break;
}
}
static void
-decode_coproc(instruction)
+decode_coproc(sd,instruction)
+ SIM_DESC sd;
unsigned int instruction;
{
int coprocnum = ((instruction >> 26) & 3);
SR = GPR[rt];
break;
/* 13 = Cause R4000 VR4100 VR4300 */
+ case 13:
+ if (code == 0x00)
+ GPR[rt] = CAUSE;
+ else
+ CAUSE = GPR[rt];
+ break;
/* 14 = EPC R4000 VR4100 VR4300 */
/* 15 = PRId R4000 VR4100 VR4300 */
+#ifdef SUBTARGET_R3900
+ /* 16 = Debug */
+ case 16:
+ if (code == 0x00)
+ GPR[rt] = Debug;
+ else
+ Debug = GPR[rt];
+ break;
+#else
/* 16 = Config R4000 VR4100 VR4300 */
+#endif
+#ifdef SUBTARGET_R3900
+ /* 17 = Debug */
+ case 17:
+ if (code == 0x00)
+ GPR[rt] = DEPC;
+ else
+ DEPC = GPR[rt];
+ break;
+#else
/* 17 = LLAddr R4000 VR4100 VR4300 */
+#endif
/* 18 = WatchLo R4000 VR4100 VR4300 */
/* 19 = WatchHi R4000 VR4100 VR4300 */
/* 20 = XContext R4000 VR4100 VR4300 */
/* CPR[0,rd] = GPR[rt]; */
default:
if (code == 0x00)
- callback->printf_filtered(callback,"Warning: MFC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
+ sim_io_printf(sd,"Warning: MFC0 %d,%d ignored (architecture specific)\n",rt,rd);
else
- callback->printf_filtered(callback,"Warning: MTC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
+ sim_io_printf(sd,"Warning: MTC0 %d,%d ignored (architecture specific)\n",rt,rd);
}
}
else if (code == 0x10 && (instruction & 0x3f) == 0x18)
if (SR & status_ERL)
{
/* Oops, not yet available */
- callback->printf_filtered(callback,"Warning: ERET when SR[ERL] set not handled yet");
+ sim_io_printf(sd,"Warning: ERET when SR[ERL] set not handled yet");
PC = EPC;
SR &= ~status_ERL;
}
SR &= ~status_EXL;
}
}
+ else if (code == 0x10 && (instruction & 0x3f) == 0x10)
+ {
+ /* RFE */
+ }
+ else if (code == 0x10 && (instruction & 0x3f) == 0x1F)
+ {
+ /* DERET */
+ Debug &= ~Debug_DM;
+ DELAYSLOT();
+ DSPC = DEPC;
+ }
else
- sim_warning("Unrecognised COP0 instruction 0x%08X at IPC = 0x%s : No handler present",instruction,pr_addr(IPC));
+ sim_io_eprintf(sd,"Unrecognised COP0 instruction 0x%08X at IPC = 0x%s : No handler present\n",instruction,pr_addr(IPC));
/* TODO: When executing an ERET or RFE instruction we should
clear LLBIT, to ensure that any out-standing atomic
read/modify/write sequence fails. */
break;
case 2: /* undefined co-processor */
- sim_warning("COP2 instruction 0x%08X at IPC = 0x%s : No handler present",instruction,pr_addr(IPC));
+ sim_io_eprintf(sd,"COP2 instruction 0x%08X at IPC = 0x%s : No handler present\n",instruction,pr_addr(IPC));
break;
case 1: /* should not occur (FPU co-processor) */
uword64 paddr;
int cca;
unsigned int instruction; /* uword64? what's this used for? FIXME! */
- int dsstate = (state & simDELAYSLOT);
#ifdef DEBUG
{
}
#endif /* DEBUG */
+ DSSTATE = (STATE & simDELAYSLOT);
#ifdef DEBUG
if (dsstate)
- callback->printf_filtered(callback,"DBG: DSPC = 0x%s\n",pr_addr(DSPC));
+ sim_io_printf(sd,"DBG: DSPC = 0x%s\n",pr_addr(DSPC));
#endif /* DEBUG */
if (AddressTranslation(PC,isINSTRUCTION,isLOAD,&paddr,&cca,isTARGET,isREAL)) {
}
#ifdef DEBUG
- callback->printf_filtered(callback,"DBG: fetched 0x%08X from PC = 0x%s\n",instruction,pr_addr(PC));
+ sim_io_printf(sd,"DBG: fetched 0x%08X from PC = 0x%s\n",instruction,pr_addr(PC));
#endif /* DEBUG */
#if !defined(FASTSIM) || defined(PROFILE)
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 */
#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"
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)
#error "Mismatch between run-time simulator code and simulation engine"
#endif
+#if (WITH_TARGET_WORD_BITSIZE != GPRLEN)
+#error "Mismatch between configure WITH_TARGET_WORD_BITSIZE and gencode GPRLEN"
+#endif
+#if (WITH_FLOATING_POINT == HARD_FLOATING_POINT != defined (HASFPU))
+#error "Mismatch between configure WITH_FLOATING_POINT and gencode HASFPU"
+#endif
#if defined(WARN_LOHI)
/* Decrement the HI/LO validity ticks */
LO1ACCESS--;
#endif /* WARN_LOHI */
-#if defined(WARN_ZERO)
/* 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
small. */
if (ZERO != 0) {
- sim_warning("The ZERO register has been updated with 0x%s (PC = 0x%s) (reset back to zero)",pr_addr(ZERO),pr_addr(IPC));
+#if defined(WARN_ZERO)
+ sim_io_eprintf(sd,"The ZERO register has been updated with 0x%s (PC = 0x%s) (reset back to zero)\n",pr_addr(ZERO),pr_addr(IPC));
+#endif /* WARN_ZERO */
ZERO = 0; /* reset back to zero before next instruction */
}
-#endif /* WARN_ZERO */
} 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 */
PC = DSPC;
- state &= ~(simDELAYSLOT | simJALDELAYSLOT);
+ CANCELDELAYSLOT();
}
if (MIPSISA < 4) { /* The following is only required on pre MIPS IV processors: */
#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);
}
#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
}
}
#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 */
}