/* MIPS Simulator definition.
- Copyright (C) 1997 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GDB, the GNU debugger.
of doing this. */
#include "itable.h"
#define MAX_INSNS (nr_itable_entries)
-#define INSN_NAME(i) itable[(i)].name
+#define INSN_NAME(cpu,i) itable[(i)].name
#endif
#include "sim-base.h"
/* Check if a value will fit within a halfword: */
#define NOTHALFWORDVALUE(v) ((((((uword64)(v)>>16) == 0) && !((v) & ((unsigned)1 << 15))) || (((((uword64)(v)>>32) == 0xFFFFFFFF) && ((((uword64)(v)>>16) & 0xFFFF) == 0xFFFF)) && ((v) & ((unsigned)1 << 15)))) ? (1 == 0) : (1 == 1))
-/* windows always looses */
-#include <signal.h>
-#ifndef SIGBUS
-#define SIGBUS SIGSEGV
-#endif
-#ifdef _WIN32
-#define SIGTRAP 5
-#define SIGQUIT 3
-#endif
-
/* Floating-point operations: */
+#include "sim-fpu.h"
+
/* FPU registers must be one of the following types. All other values
are reserved (and undefined). */
typedef enum {
range, and are used in the register status vector. */
fmt_unknown = 0x10000000,
fmt_uninterpreted = 0x20000000,
+ fmt_uninterpreted_32 = 0x40000000,
+ fmt_uninterpreted_64 = 0x80000000,
} FP_formats;
-unsigned64 value_fpr PARAMS ((SIM_DESC sd, address_word cia, int fpr, FP_formats));
-#define ValueFPR(FPR,FMT) value_fpr (sd, cia, (FPR), (FMT))
+unsigned64 value_fpr PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int fpr, FP_formats));
+#define ValueFPR(FPR,FMT) value_fpr (SD, CPU, cia, (FPR), (FMT))
-void store_fpr PARAMS ((SIM_DESC sd, address_word cia, int fpr, FP_formats fmt, unsigned64 value));
-#define StoreFPR(FPR,FMT,VALUE) store_fpr (sd, cia, (FPR), (FMT), (VALUE))
+void store_fpr PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int fpr, FP_formats fmt, unsigned64 value));
+#define StoreFPR(FPR,FMT,VALUE) store_fpr (SD, CPU, cia, (FPR), (FMT), (VALUE))
int NaN PARAMS ((unsigned64 op, FP_formats fmt));
int Infinity PARAMS ((unsigned64 op, 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, address_word cia, int rm, unsigned64 op, FP_formats from, FP_formats to));
-#define Convert(rm,op,from,to) convert(sd,cia,rm,op,from,to)
+unsigned64 Max PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
+unsigned64 Min PARAMS ((unsigned64 op1, unsigned64 op2, FP_formats fmt));
+unsigned64 convert PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int rm, unsigned64 op, FP_formats from, FP_formats to));
+#define Convert(rm,op,from,to) \
+convert (SD, CPU, cia, rm, op, from, to)
/* Macro to update FPSR condition-code field. This is complicated by
the fact that there is a hole in the index range of the bits within
int bit = ((cc == 0) ? 23 : (24 + (cc)));\
FCSR = ((FCSR & ~(1 << bit)) | ((v) << bit));\
}
-#define GETFCC(cc) (((((cc) == 0) ? (FCSR & (1 << 23)) : (FCSR & (1 << (24 + (cc))))) != 0) ? 1 : 0)
+#define GETFCC(cc) (((((cc) == 0) ? (FCSR & (1 << 23)) : (FCSR & (1 << (24 + (cc))))) != 0) ? 1U : 0)
/* This should be the COC1 value at the start of the preceding
instruction: */
#define PREVCOC1() ((STATE & simPCOC1) ? 1 : 0)
#if 1
-#define SizeFGR() (WITH_TARGET_WORD_BITSIZE)
+#define SizeFGR() (WITH_TARGET_FLOATING_POINT_BITSIZE)
#else
/* They depend on the CPU being simulated */
#define SizeFGR() ((WITH_TARGET_WORD_BITSIZE == 64 && ((SR & status_FR) == 1)) ? 64 : 32)
#define FP_RM_TOMINF (3) /* Round to Minus infinity (Floor) */
#define GETRM() (int)((FCSR >> FP_SH_RM) & FP_MASK_RM)
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#ifdef SKY_FUNIT
+#include <assert.h>
+#include "wf.h"
+#endif
+#endif
+/* end-sanitize-sky */
+
+
+
+
+
+/* HI/LO register accesses */
+
+/* For some MIPS targets, the HI/LO registers have certain timing
+ restrictions in that, for instance, a read of a HI register must be
+ separated by at least three instructions from a preceeding read.
+
+ The struct below is used to record the last access by each of A MT,
+ MF or other OP instruction to a HI/LO register. See mips.igen for
+ more details. */
+
+typedef struct _hilo_access {
+ signed64 timestamp;
+ address_word cia;
+} hilo_access;
+
+typedef struct _hilo_history {
+ hilo_access mt;
+ hilo_access mf;
+ hilo_access op;
+} hilo_history;
+
+
/* Integer ALU operations: */
#define ALU32_END(ANS) \
if (ALU32_HAD_OVERFLOW) \
SignalExceptionIntegerOverflow (); \
- (ANS) = ALU32_OVERFLOW_RESULT
+ (ANS) = (signed32) ALU32_OVERFLOW_RESULT
#define ALU64_END(ANS) \
SignalExceptionIntegerOverflow (); \
(ANS) = ALU64_OVERFLOW_RESULT;
+
/* start-sanitize-r5900 */
+/* Figure 10-5 FPU Control/Status Register.
+ Note: some of these bits are different to what is found in a
+ standard MIPS manual. */
+enum {
+ R5900_FCSR_C = BIT (23), /* OK */
+ R5900_FCSR_I = BIT (17),
+ R5900_FCSR_D = BIT (16),
+ R5900_FCSR_O = BIT (15),
+ R5900_FCSR_U = BIT (14),
+ R5900_FCSR_CAUSE = MASK (16,14),
+ R5900_FCSR_SI = BIT (6),
+ R5900_FCSR_SD = BIT (5),
+ R5900_FCSR_SO = BIT (4),
+ R5900_FCSR_SU = BIT (3),
+};
+
+/* Table 10-1 FP format values.
+ Note: some of these bits are different to what is found in a
+ standard MIPS manual. */
+enum {
+ R5900_EXPMAX = 128,
+ R5900_EXPMIN = -127,
+ R5900_EXPBIAS = 127,
+};
+
+/* MAX and MIN FP values */
+enum {
+ R5900_FPMAX = LSMASK32 (30, 0),
+ R5900_FPMIN = LSMASK32 (31, 0),
+};
+
+
+
+typedef struct _sim_r5900_cpu {
+
+ /* The R5900 has 32 x 128bit general purpose registers.
+ Fortunatly, the high 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 gpr1[32];
+#define GPR1 ((CPU)->r5900.gpr1)
+ signed_word lo1;
+ signed_word hi1;
+#define LO1 ((CPU)->r5900.lo1)
+#define HI1 ((CPU)->r5900.hi1)
+
+ /* The R5900 defines a shift amount register, that controls the
+ amount of certain shift instructions */
+ unsigned_word sa; /* the shift amount register */
+#define REGISTER_SA (124) /* GET RID IF THIS! */
+#define SA ((CPU)->r5900.sa)
+
+ /* The R5900, in addition to the (almost) standard floating point
+ registers, defines a 32 bit accumulator. This is used in
+ multiply/accumulate style instructions */
+ fp_word acc; /* floating-point accumulator */
+#define ACC ((CPU)->r5900.acc)
+
+ /* See comments below about needing to count cycles between updating
+ and setting HI/LO registers */
+ hilo_history hi1_history;
+#define HI1HISTORY (&(CPU)->r5900.hi1_history)
+ hilo_history lo1_history;
+#define LO1HISTORY (&(CPU)->r5900.lo1_history)
+
+} sim_r5900_cpu;
+
#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 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(&GPR[R], &GPR1[R], I)
+#define GPR_SH(R,I) SUB_REG_SH(&GPR[R], &GPR1[R], I)
+#define GPR_SW(R,I) SUB_REG_SW(&GPR[R], &GPR1[R], I)
+#define GPR_SD(R,I) SUB_REG_SD(&GPR[R], &GPR1[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(&GPR[R], &GPR1[R], I)
+#define GPR_UH(R,I) SUB_REG_UH(&GPR[R], &GPR1[R], I)
+#define GPR_UW(R,I) SUB_REG_UW(&GPR[R], &GPR1[R], I)
+#define GPR_UD(R,I) SUB_REG_UD(&GPR[R], &GPR1[R], I)
#define RS_SB(I) SUB_REG_SB(&rs_reg, &rs_reg1, I)
+/* The following is probably not used for MIPS IV onwards: */
+/* Slots for delayed register updates. For the moment we just have a
+ fixed number of slots (rather than a more generic, dynamic
+ system). This keeps the simulator fast. However, we only allow
+ for the register update to be delayed for a single instruction
+ cycle. */
+#define PSLOTS (8) /* Maximum number of instruction cycles */
+
+typedef struct _pending_write_queue {
+ int in;
+ int out;
+ int total;
+ int slot_delay[PSLOTS];
+ int slot_size[PSLOTS];
+ int slot_bit[PSLOTS];
+ void *slot_dest[PSLOTS];
+ unsigned64 slot_value[PSLOTS];
+} pending_write_queue;
+
+#ifndef PENDING_TRACE
+#define PENDING_TRACE 0
+#endif
+#define PENDING_IN ((CPU)->pending.in)
+#define PENDING_OUT ((CPU)->pending.out)
+#define PENDING_TOTAL ((CPU)->pending.total)
+#define PENDING_SLOT_SIZE ((CPU)->pending.slot_size)
+#define PENDING_SLOT_BIT ((CPU)->pending.slot_size)
+#define PENDING_SLOT_DELAY ((CPU)->pending.slot_delay)
+#define PENDING_SLOT_DEST ((CPU)->pending.slot_dest)
+#define PENDING_SLOT_VALUE ((CPU)->pending.slot_value)
+
+/* Invalidate the pending write queue, all pending writes are
+ discarded. */
+
+#define PENDING_INVALIDATE() \
+memset (&(CPU)->pending, 0, sizeof ((CPU)->pending))
+
+/* Schedule a write to DEST for N cycles time. For 64 bit
+ destinations, schedule two writes. For floating point registers,
+ the caller should schedule a write to both the dest register and
+ the FPR_STATE register. When BIT is non-negative, only BIT of DEST
+ is updated. */
+
+#define PENDING_SCHED(DEST,VAL,DELAY,BIT) \
+ do { \
+ if (PENDING_SLOT_DEST[PENDING_IN] != NULL) \
+ sim_engine_abort (SD, CPU, cia, \
+ "PENDING_SCHED - buffer overflow\n"); \
+ if (PENDING_TRACE) \
+ sim_io_printf (SD, "PENDING_SCHED - dest 0x%lx, val 0x%lx, pending_in %d, pending_out %d, pending_total %d\n", (unsigned long) (DEST), (unsigned long) (VAL), PENDING_IN, PENDING_OUT, PENDING_TOTAL); \
+ PENDING_SLOT_DELAY[PENDING_IN] = (DELAY) + 1; \
+ PENDING_SLOT_DEST[PENDING_IN] = &(DEST); \
+ PENDING_SLOT_VALUE[PENDING_IN] = (VAL); \
+ PENDING_SLOT_SIZE[PENDING_IN] = sizeof (DEST); \
+ PENDING_SLOT_BIT[PENDING_IN] = (BIT); \
+ } while (0)
+
+#define PENDING_WRITE(DEST,VAL,DELAY) PENDING_SCHED(DEST,VAL,DELAY,-1)
+#define PENDING_BIT(DEST,VAL,DELAY,BIT) PENDING_SCHED(DEST,VAL,DELAY,BIT)
+
+#define PENDING_TICK() pending_tick (SD, CPU, cia)
+
+#define PENDING_FLUSH() abort () /* think about this one */
+#define PENDING_FP() abort () /* think about this one */
+
+/* For backward compatibility */
+#define PENDING_FILL(R,VAL) \
+{ \
+ if ((R) >= FGRIDX && (R) < FGRIDX + NR_FGR) \
+ PENDING_SCHED(FGR[(R) - FGRIDX], VAL, 2, -1); \
+ else \
+ PENDING_SCHED(GPR[(R)], VAL, 2, -1); \
+}
+
+
struct _sim_cpu {
/* The following are internal simulator state variables: */
-#define CPU_CIA(CPU) (PC)
+#define CIA_GET(CPU) ((CPU)->registers[PCIDX] + 0)
+#define CIA_SET(CPU,CIA) ((CPU)->registers[PCIDX] = (CIA))
address_word dspc; /* delay-slot PC */
-#define DSPC ((STATE_CPU (sd,0))->dspc)
+#define DSPC ((CPU)->dspc)
+#if !WITH_IGEN
/* Issue a delay slot instruction immediatly by re-calling
idecode_issue */
#define DELAY_SLOT(TARGET) \
do { \
address_word target = (TARGET); \
instruction_word delay_insn; \
- sim_events_slip (sd, 1); \
- CIA = CIA + 4; \
+ sim_events_slip (SD, 1); \
+ CIA = CIA + 4; /* NOTE not mips16 */ \
STATE |= simDELAYSLOT; \
- delay_insn = IMEM (CIA); \
- idecode_issue (sd, delay_insn, (CIA)); \
+ delay_insn = IMEM32 (CIA); /* NOTE not mips16 */ \
+ idecode_issue (CPU_, delay_insn, (CIA)); \
STATE &= ~simDELAYSLOT; \
NIA = target; \
} while (0)
#define NULLIFY_NEXT_INSTRUCTION() \
do { \
- sim_events_slip (sd, 1); \
+ sim_events_slip (SD, 1); \
+ dotrace (SD, CPU, tracefh, 2, NIA, 4, "load instruction"); \
NIA = CIA + 8; \
} while (0)
-
+#else
+#define DELAY_SLOT(TARGET) NIA = delayslot32 (SD_, (TARGET))
+#define NULLIFY_NEXT_INSTRUCTION() NIA = nullify_next_insn32 (SD_)
+#endif
/* State of the simulator */
unsigned int state;
unsigned int dsstate;
-#define STATE ((STATE_CPU (sd,0))->state)
-#define DSSTATE ((STATE_CPU (sd,0))->dsstate)
+#define STATE ((CPU)->state)
+#define DSSTATE ((CPU)->dsstate)
/* Flags in the "state" variable: */
#define simHALTEX (1 << 2) /* 0 = run; 1 = halt on exception */
#define simSIGINT (1 << 28) /* 0 = do nothing; 1 = SIGINT has occured */
#define simJALDELAYSLOT (1 << 29) /* 1 = in jal delay slot */
-
+#define ENGINE_ISSUE_PREFIX_HOOK() \
+ { \
+ /* Perform any pending writes */ \
+ PENDING_TICK(); \
+ /* Set previous flag, depending on current: */ \
+ if (STATE & simPCOC0) \
+ STATE |= simPCOC1; \
+ else \
+ STATE &= ~simPCOC1; \
+ /* and update the current value: */ \
+ if (GETFCC(0)) \
+ STATE |= simPCOC0; \
+ else \
+ STATE &= ~simPCOC0; \
+ }
/* This is nasty, since we have to rely on matching the register
/* end-sanitize-r5900 */
#endif
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#ifndef TM_TXVU_H
+/* Number of machine registers */
+#define NUM_VU_REGS 153
+#define NUM_VU_INTEGER_REGS 16
+
+#define NUM_VIF_REGS 26
+
+#define FIRST_VEC_REG 25
+#define NUM_CORE_REGS 128
+
+#undef NUM_REGS
+#define NUM_REGS (NUM_CORE_REGS + 2*(NUM_VU_REGS) + 2*(NUM_VIF_REGS))
+#endif /* no tm-txvu.h */
+#endif /* TARGET_SKY */
+/* end-sanitize-sky */
+
+enum float_operation
+/* start-sanitize-sky */
+/* NOTE: THE VALUES of THESE CONSTANTS MUST BE IN SYNC WITH THOSE IN WF.H */
+/* end-sanitize-sky */
+ {
+ FLOP_ADD, FLOP_SUB, FLOP_MUL, FLOP_MADD,
+ FLOP_MSUB, FLOP_MAX=10, FLOP_MIN, FLOP_ABS,
+ FLOP_ITOF0=14, FLOP_FTOI0=18, FLOP_NEG=23
+ };
+
/* 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. */
unsigned_word registers[LAST_EMBED_REGNUM + 1];
int register_widths[NUM_REGS];
-#define REGISTERS ((STATE_CPU (sd,0))->registers)
+#define REGISTERS ((CPU)->registers)
#define GPR (®ISTERS[0])
+#define GPR_SET(N,VAL) (REGISTERS[(N)] = (VAL))
+
+ /* While space is allocated for the floating point registers in the
+ main registers array, they are stored separatly. This is because
+ their size may not necessarily match the size of either the
+ general-purpose or system specific registers */
+#define NR_FGR (32)
#define FGRIDX (38)
-#define FGR (®ISTERS[FGRIDX])
+ fp_word fgr[NR_FGR];
+#define FGR ((CPU)->fgr)
+
#define LO (REGISTERS[33])
#define HI (REGISTERS[34])
-#define PC (REGISTERS[37])
+#define PCIDX 37
+#define PC (REGISTERS[PCIDX])
#define CAUSE (REGISTERS[36])
#define SRIDX (32)
#define SR (REGISTERS[SRIDX]) /* CPU status register */
#define EPC (REGISTERS[88])
#define COCIDX (LAST_EMBED_REGNUM + 2) /* special case : outside the normal range */
+ unsigned_word c0_config_reg;
+#define C0_CONFIG ((CPU)->c0_config_reg)
+
/* The following are pseudonyms for standard registers */
#define ZERO (REGISTERS[0])
#define V0 (REGISTERS[2])
#define A1 (REGISTERS[5])
#define A2 (REGISTERS[6])
#define A3 (REGISTERS[7])
-#define SP (REGISTERS[29])
-#define RA (REGISTERS[31])
+#define T8IDX 24
+#define T8 (REGISTERS[T8IDX])
+#define SPIDX 29
+#define SP (REGISTERS[SPIDX])
+#define RAIDX 31
+#define RA (REGISTERS[RAIDX])
+
+ /* While space is allocated in the main registers arrray for some of
+ the COP0 registers, that space isn't sufficient. Unknown COP0
+ registers overflow into the array below */
+
+#define NR_COP0_GPR 32
+ unsigned_word cop0_gpr[NR_COP0_GPR];
+#define COP0_GPR ((CPU)->cop0_gpr)
+ /* start-sanitize-r5900 */
+#define NR_COP0_BP 8
+ unsigned_word cop0_bp[NR_COP0_BP];
+#define COP0_BP ((CPU)->cop0_bp)
+#define NR_COP0_P 64
+ unsigned_word cop0_p[NR_COP0_P];
+#define COP0_P ((CPU)->cop0_p)
+ /* end-sanitize-r5900 */
+
/* 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)
-
- /* The following are not used for MIPS IV onwards: */
-#define PENDING_FILL(r,v) {\
-/* printf("DBG: FILL BEFORE pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL); */\
- if (PENDING_SLOT_REG[PENDING_IN] != (LAST_EMBED_REGNUM + 1))\
- sim_io_eprintf(sd,"Attempt to over-write pending value\n");\
- PENDING_SLOT_COUNT[PENDING_IN] = 2;\
- PENDING_SLOT_REG[PENDING_IN] = (r);\
- PENDING_SLOT_VALUE[PENDING_IN] = (uword64)(v);\
-/*printf("DBG: FILL reg %d value = 0x%s\n",(r),pr_addr(v));*/\
- PENDING_TOTAL++;\
- PENDING_IN++;\
- if (PENDING_IN == PSLOTS)\
- PENDING_IN = 0;\
-/*printf("DBG: FILL AFTER pending_in = %d, pending_out = %d, pending_total = %d\n",PENDING_IN,PENDING_OUT,PENDING_TOTAL);*/\
- }
+#define FPR_STATE ((CPU)->fpr_state)
+ pending_write_queue pending;
/* LLBIT = Load-Linked bit. A bit of "virtual" state used by atomic
read-write instructions. It is set when a linked load occurs. It
no longer be atomic. In particular, it is cleared by exception
return instructions. */
int llbit;
-#define LLBIT ((STATE_CPU (sd, 0))->llbit)
+#define LLBIT ((CPU)->llbit)
-/* The HIACCESS and LOACCESS counts are used to ensure that
- corruptions caused by using the HI or LO register to close to a
- following operation are spotted. */
+/* The HIHISTORY and LOHISTORY timestamps are used to ensure that
+ corruptions caused by using the HI or LO register too close to a
+ following operation is spotted. See mips.igen for more details. */
- int hiaccess;
- int loaccess;
-#define HIACCESS ((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 */
+ hilo_history hi_history;
+#define HIHISTORY (&(CPU)->hi_history)
+ hilo_history lo_history;
+#define LOHISTORY (&(CPU)->lo_history)
+
+ /* start-sanitize-branchbug4011 */
#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)
+ int branchbug4011_option;
+#define BRANCHBUG4011_OPTION ((CPU)->branchbug4011_option)
+ address_word branchbug4011_last_target;
+#define BRANCHBUG4011_LAST_TARGET ((CPU)->branchbug4011_last_target)
+ address_word branchbug4011_last_cia;
+#define BRANCHBUG4011_LAST_CIA ((CPU)->branchbug4011_last_cia)
+
+#define check_branch_bug() (check_4011_branch_bug (_SD))
+#define mark_branch_bug(TARGET) (mark_4011_branch_bug (_SD,TARGET))
#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));\
-}
- /* start-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 */
+ /* end-sanitize-branchbug4011 */
+#define check_branch_bug()
+#define mark_branch_bug(TARGET)
+ /* start-sanitize-branchbug4011 */
#endif
-
-
+ /* end-sanitize-branchbug4011 */
/* 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)
+ sim_r5900_cpu r5900;
/* end-sanitize-r5900 */
/* start-sanitize-vr5400 */
+ /* The MDMX ISA has a very very large accumulator */
+ unsigned8 acc[3 * 8];
/* end-sanitize-vr5400 */
+ /* start-sanitize-sky */
-
-
+#ifdef TARGET_SKY
+ /* Device on which instruction issue last occured. */
+ char cur_device;
+#endif
+ /* end-sanitize-sky */
sim_cpu_base base;
};
struct swatch watch;
- sim_cpu cpu[1];
+ sim_cpu cpu[MAX_NR_PROCESSORS];
#if (WITH_SMP)
#define STATE_CPU(sd,n) (&(sd)->cpu[n])
#else
#define STATE_CPU(sd,n) (&(sd)->cpu[0])
#endif
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#ifdef SKY_FUNIT
+ /* Record of option for floating point implementation type. */
+ int fp_type_opt;
+#define STATE_FP_TYPE_OPT(sd) ((sd)->fp_type_opt)
+#define STATE_FP_TYPE_OPT_ACCURATE 0x80000000
+#endif
+#endif
+/* end-sanitize-sky */
+
sim_state_base base;
};
#define ksu_unknown (0x3)
#define status_IE (1 << 0) /* Interrupt enable */
+#define status_EIE (1 << 16) /* Enable Interrupt Enable */
#define status_EXL (1 << 1) /* Exception level */
#define status_RE (1 << 25) /* Reverse Endian in user mode */
#define status_FR (1 << 26) /* enables MIPS III additional FP registers */
#define status_TS (1 << 21) /* TLB shutdown has occurred */
#define status_ERL (1 << 2) /* Error level */
#define status_RP (1 << 27) /* Reduced Power mode */
+/* start-sanitize-r5900 */
+#define status_CU0 (1 << 28) /* COP0 usable */
+#define status_CU1 (1 << 29) /* COP1 usable */
+#define status_CU2 (1 << 30) /* COP2 usable */
+/* end-sanitize-r5900 */
+
+/* Specializations for TX39 family */
+#define status_IEc (1 << 0) /* Interrupt enable (current) */
+#define status_KUc (1 << 1) /* Kernel/User mode */
+#define status_IEp (1 << 2) /* Interrupt enable (previous) */
+#define status_KUp (1 << 3) /* Kernel/User mode */
+#define status_IEo (1 << 4) /* Interrupt enable (old) */
+#define status_KUo (1 << 5) /* Kernel/User mode */
+#define status_IM_mask (0xff) /* Interrupt mask */
+#define status_IM_shift (8)
+#define status_NMI (1 << 20) /* NMI */
+#define status_NMI (1 << 20) /* NMI */
+
+#define cause_EXC_mask (0x1f) /* Exception code */
+#define cause_EXC_shift (2)
+#define cause_SW0 (1 << 8) /* Software interrupt 0 */
+#define cause_SW1 (1 << 9) /* Software interrupt 1 */
+#define cause_IP_mask (0x3f) /* Interrupt pending field */
+#define cause_IP_shift (10)
+#define cause_CE_mask (0x3) /* Coprocessor error */
+#define cause_CE_shift (28)
+
+#define cause_BD ((unsigned)1 << 31) /* Exception in branch delay slot */
-#define cause_BD ((unsigned)1 << 31) /* Exception in branch delay slot */
/* 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
value is. */
/* UserMode */
+#ifdef SUBTARGET_R3900
+#define UserMode ((SR & status_KUc) ? 1 : 0)
+#else
#define UserMode ((((SR & status_KSU_mask) >> status_KSU_shift) == ksu_user) ? 1 : 0)
+#endif /* SUBTARGET_R3900 */
/* BigEndianMem */
/* Hardware configuration. Affects endianness of LoadMemory and
#define FPE (15)
#define DebugBreakPoint (16)
#define Watch (23)
+#define NMIReset (31)
+
/* 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)
-void signal_exception (SIM_DESC sd, address_word cia, int exception, ...);
-#define SignalException(exc,instruction) signal_exception (sd, cia, (exc), (instruction))
-#define SignalExceptionInterrupt() signal_exception (sd, NULL_CIA, Interrupt)
-#define SignalExceptionInstructionFetch() signal_exception (sd, cia, InstructionFetch)
-#define SignalExceptionAddressStore() signal_exception (sd, cia, AddressStore)
-#define SignalExceptionAddressLoad() signal_exception (sd, cia, AddressLoad)
-#define SignalExceptionSimulatorFault(buf) signal_exception (sd, cia, SimulatorFault, buf)
-#define SignalExceptionFPE() signal_exception (sd, cia, FPE)
-#define SignalExceptionIntegerOverflow() signal_exception (sd, cia, IntegerOverflow)
-#define SignalExceptionCoProcessorUnusable() signal_exception (sd, cia, CoProcessorUnusable)
+/* The following break instructions are reserved for use by the
+ simulator. The first is used to halt the simulation. The second
+ is used by gdb for break-points. NOTE: Care must be taken, since
+ this value may be used in later revisions of the MIPS ISA. */
+#define HALT_INSTRUCTION_MASK (0x03FFFFC0)
+#define HALT_INSTRUCTION (0x03ff000d)
+#define HALT_INSTRUCTION2 (0x0000ffcd)
-/* Co-processor accesses */
+/* start-sanitize-sky */
+#define HALT_INSTRUCTION_PASS (0x03fffc0d)
+#define HALT_INSTRUCTION_FAIL (0x03ffffcd)
+/* end-sanitize-sky */
+
+#define BREAKPOINT_INSTRUCTION (0x0005000d)
+#define BREAKPOINT_INSTRUCTION2 (0x0000014d)
-void cop_lw PARAMS ((SIM_DESC sd, address_word cia, int coproc_num, int coproc_reg, unsigned int memword));
-void cop_ld PARAMS ((SIM_DESC sd, address_word cia, int coproc_num, int coproc_reg, uword64 memword));
-unsigned int cop_sw PARAMS ((SIM_DESC sd, address_word cia, int coproc_num, int coproc_reg));
-uword64 cop_sd PARAMS ((SIM_DESC sd, address_word cia, int coproc_num, int coproc_reg));
-#define COP_LW(coproc_num,coproc_reg,memword) cop_lw(sd,cia,coproc_num,coproc_reg,memword)
-#define COP_LD(coproc_num,coproc_reg,memword) cop_ld(sd,cia,coproc_num,coproc_reg,memword)
-#define COP_SW(coproc_num,coproc_reg) cop_sw(sd,cia,coproc_num,coproc_reg)
-#define COP_SD(coproc_num,coproc_reg) cop_sd(sd,cia,coproc_num,coproc_reg)
+void interrupt_event (SIM_DESC sd, void *data);
-void decode_coproc PARAMS ((SIM_DESC sd, address_word cia, unsigned int instruction));
-#define DecodeCoproc(instruction) decode_coproc(sd, cia, (instruction))
+void signal_exception (SIM_DESC sd, sim_cpu *cpu, address_word cia, int exception, ...);
+#define SignalException(exc,instruction) signal_exception (SD, CPU, cia, (exc), (instruction))
+#define SignalExceptionInterrupt() signal_exception (SD, CPU, cia, Interrupt)
+#define SignalExceptionInstructionFetch() signal_exception (SD, CPU, cia, InstructionFetch)
+#define SignalExceptionAddressStore() signal_exception (SD, CPU, cia, AddressStore)
+#define SignalExceptionAddressLoad() signal_exception (SD, CPU, cia, AddressLoad)
+#define SignalExceptionSimulatorFault(buf) signal_exception (SD, CPU, cia, SimulatorFault, buf)
+#define SignalExceptionFPE() signal_exception (SD, CPU, cia, FPE)
+#define SignalExceptionIntegerOverflow() signal_exception (SD, CPU, cia, IntegerOverflow)
+#define SignalExceptionCoProcessorUnusable() signal_exception (SD, CPU, cia, CoProcessorUnusable)
+#define SignalExceptionNMIReset() signal_exception (SD, CPU, cia, NMIReset)
+
+/* Co-processor accesses */
+
+void cop_lw PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg, unsigned int memword));
+void cop_ld PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg, uword64 memword));
+unsigned int cop_sw PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg));
+uword64 cop_sd PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int coproc_num, int coproc_reg));
+
+#define COP_LW(coproc_num,coproc_reg,memword) \
+cop_lw (SD, CPU, cia, coproc_num, coproc_reg, memword)
+#define COP_LD(coproc_num,coproc_reg,memword) \
+cop_ld (SD, CPU, cia, coproc_num, coproc_reg, memword)
+#define COP_SW(coproc_num,coproc_reg) \
+cop_sw (SD, CPU, cia, coproc_num, coproc_reg)
+#define COP_SD(coproc_num,coproc_reg) \
+cop_sd (SD, CPU, cia, coproc_num, coproc_reg)
+
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+void cop_lq PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia,
+ int coproc_num, int coproc_reg, unsigned128 memword));
+unsigned128 cop_sq PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia,
+ int coproc_num, int coproc_reg));
+#define COP_LQ(coproc_num,coproc_reg,memword) \
+cop_lq (SD, CPU, cia, coproc_num, coproc_reg, memword)
+#define COP_SQ(coproc_num,coproc_reg) \
+cop_sq (SD, CPU, cia, coproc_num, coproc_reg)
+#endif /* TARGET_SKY */
+/* end-sanitize-sky */
+
+void decode_coproc PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, unsigned int instruction));
+#define DecodeCoproc(instruction) \
+decode_coproc (SD, CPU, cia, (instruction))
#define AccessLength_DOUBLEWORD (7)
#define AccessLength_QUADWORD (15)
-int address_translation PARAMS ((SIM_DESC sd, address_word cia, address_word vAddr, int IorD, int LorS, address_word *pAddr, int *CCA, int raw));
+#if (WITH_IGEN)
+#define LOADDRMASK (WITH_TARGET_WORD_BITSIZE == 64 \
+ ? AccessLength_DOUBLEWORD /*7*/ \
+ : AccessLength_WORD /*3*/)
+#define PSIZE (WITH_TARGET_ADDRESS_BITSIZE)
+#endif
+
+
+INLINE_SIM_MAIN (int) address_translation PARAMS ((SIM_DESC sd, sim_cpu *, address_word cia, address_word vAddr, int IorD, int LorS, address_word *pAddr, int *CCA, int raw));
#define AddressTranslation(vAddr,IorD,LorS,pAddr,CCA,host,raw) \
-address_translation(sd,cia,vAddr,IorD,LorS,pAddr,CCA,raw)
+address_translation (SD, CPU, cia, vAddr, IorD, LorS, pAddr, CCA, raw)
-void load_memory PARAMS ((SIM_DESC sd, address_word cia, uword64* memvalp, uword64* memval1p, int CCA, int AccessLength, address_word pAddr, address_word vAddr, int IorD));
+INLINE_SIM_MAIN (void) load_memory PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, uword64* memvalp, uword64* memval1p, int CCA, unsigned int AccessLength, address_word pAddr, address_word vAddr, int IorD));
#define LoadMemory(memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD,raw) \
-load_memory(sd,cia,memvalp,memval1p,CCA,AccessLength,pAddr,vAddr,IorD)
+load_memory (SD, CPU, cia, memvalp, memval1p, CCA, AccessLength, pAddr, vAddr, IorD)
-void store_memory PARAMS ((SIM_DESC sd, address_word cia, int CCA, int AccessLength, uword64 MemElem, uword64 MemElem1, address_word pAddr, address_word vAddr));
+INLINE_SIM_MAIN (void) store_memory PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int CCA, unsigned int AccessLength, uword64 MemElem, uword64 MemElem1, address_word pAddr, address_word vAddr));
#define StoreMemory(CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr,raw) \
-store_memory(sd,cia,CCA,AccessLength,MemElem,MemElem1,pAddr,vAddr)
+store_memory (SD, CPU, cia, CCA, AccessLength, MemElem, MemElem1, pAddr, vAddr)
+
+INLINE_SIM_MAIN (void) cache_op PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int op, address_word pAddr, address_word vAddr, unsigned int instruction));
+#define CacheOp(op,pAddr,vAddr,instruction) \
+cache_op (SD, CPU, cia, op, pAddr, vAddr, instruction)
+
+INLINE_SIM_MAIN (void) sync_operation PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int stype));
+#define SyncOperation(stype) \
+sync_operation (SD, CPU, cia, (stype))
+
+INLINE_SIM_MAIN (void) prefetch PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int CCA, address_word pAddr, address_word vAddr, int DATA, int hint));
+#define Prefetch(CCA,pAddr,vAddr,DATA,hint) \
+prefetch (SD, CPU, cia, CCA, pAddr, vAddr, DATA, hint)
+
+INLINE_SIM_MAIN (unsigned32) ifetch32 PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, address_word vaddr));
+#define IMEM32(CIA) ifetch32 (SD, CPU, (CIA), (CIA))
+INLINE_SIM_MAIN (unsigned16) ifetch16 PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, address_word vaddr));
+#define IMEM16(CIA) ifetch16 (SD, CPU, (CIA), ((CIA) & ~1))
+#define IMEM16_IMMED(CIA,NR) ifetch16 (SD, CPU, (CIA), ((CIA) & ~1) + 2 * (NR))
+
+void dotrace PARAMS ((SIM_DESC sd, sim_cpu *cpu, FILE *tracefh, int type, SIM_ADDR address, int width, char *comment, ...));
+extern FILE *tracefh;
+
+INLINE_SIM_MAIN (void) pending_tick PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia));
+
+char* pr_addr PARAMS ((SIM_ADDR addr));
+char* pr_uword64 PARAMS ((uword64 addr));
-void cache_op PARAMS ((SIM_DESC sd, address_word cia, int op, address_word pAddr, address_word vAddr, unsigned int instruction));
-#define CacheOp(op,pAddr,vAddr,instruction) cache_op(sd,cia,op,pAddr,vAddr,instruction)
+/* start-sanitize-sky */
+#ifdef TARGET_SKY
+#ifdef SIM_ENGINE_HALT_HOOK
+#undef SIM_ENGINE_HALT_HOOK
+#endif
+
+void sky_sim_engine_halt PARAMS ((SIM_DESC sd, sim_cpu *last, sim_cia cia));
+#define SIM_ENGINE_HALT_HOOK(sd, last, cia) sky_sim_engine_halt(sd, last, cia)
+
+#ifdef SIM_ENGINE_RESTART_HOOK
+#undef SIM_ENGINE_RESTART_HOOK
+#endif
-void sync_operation PARAMS ((SIM_DESC sd, address_word cia, int stype));
-#define SyncOperation(stype) sync_operation (sd, cia, (stype))
+void sky_sim_engine_restart PARAMS ((SIM_DESC sd, sim_cpu *last, sim_cia cia));
+#define SIM_ENGINE_RESTART_HOOK(sd, L, pc) sky_sim_engine_restart(sd, L, pc)
-void prefetch PARAMS ((SIM_DESC sd, address_word cia, int CCA, address_word pAddr, address_word vAddr, int DATA, int hint));
-#define Prefetch(CCA,pAddr,vAddr,DATA,hint) prefetch(sd,cia,CCA,pAddr,vAddr,DATA,hint)
+/* for resume/suspend modules */
+SIM_RC sky_sim_module_install PARAMS ((SIM_DESC sd));
+
+#define MODULE_LIST sky_sim_module_install,
+
+#ifndef TM_TXVU_H /* In case GDB hasn't been configured yet */
+enum txvu_cpu_context
+{
+ TXVU_CPU_AUTO = -1, /* context-sensitive context */
+ TXVU_CPU_MASTER = 0, /* R5900 core */
+ TXVU_CPU_VU0 = 1, /* Vector units */
+ TXVU_CPU_VU1 = 2,
+ TXVU_CPU_VIF0 = 3, /* FIFO's */
+ TXVU_CPU_VIF1 = 4,
+ TXVU_CPU_LAST /* Count of context types */
+};
-unsigned32 ifetch32 PARAMS ((SIM_DESC sd, address_word cia, address_word vaddr));
-#define IMEM(CIA) ifetch32 (SD, (CIA), (CIA))
+/* memory segment for communication with GDB */
+#define GDB_COMM_AREA 0x21010000 /* Random choice */
+#define GDB_COMM_SIZE 0x4000
+/* Memory address containing last device to execute */
+#define LAST_DEVICE GDB_COMM_AREA
+
+/* The FIFO breakpoint count and table */
+#define FIFO_BPT_CNT (GDB_COMM_AREA + 4)
+#define FIFO_BPT_TBL (GDB_COMM_AREA + 8)
+
+/* Each element of the breakpoint table is three four-byte integers. */
+#define BPT_ELEM_SZ 4*3
+
+#define TXVU_VU_BRK_MASK 0x02 /* Breakpoint bit is #57 for VU insns */
+#define TXVU_VIF_BRK_MASK 0x80 /* Use interrupt bit for VIF insns */
+
+#endif /* !TM_TXVU_H */
+#endif /* TARGET_SKY */
+/* end-sanitize-sky */
+
+#if H_REVEALS_MODULE_P (SIM_MAIN_INLINE)
+#include "sim-main.c"
+#endif
#endif