/* 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.
#define WITH_WATCHPOINTS 1
#define WITH_MODULO_MEMORY 1
+
+#define SIM_CORE_SIGNAL(SD,CPU,CIA,MAP,NR_BYTES,ADDR,TRANSFER,ERROR) \
+mips_core_signal ((SD), (CPU), (CIA), (MAP), (NR_BYTES), (ADDR), (TRANSFER), (ERROR))
+
#include "sim-basics.h"
typedef address_word sim_cia;
-#if (WITH_IGEN)
-/* Get the number of instructions. FIXME: must be a more elegant way
- of doing this. */
-#include "itable.h"
-#define MAX_INSNS (nr_itable_entries)
-#define INSN_NAME(i) itable[(i)].name
-#endif
-
#include "sim-base.h"
#define WORD64(h,l) ((word64)((SET64HI(h)|SET64LO(l))))
#define UWORD64(h,l) (SET64HI(h)|SET64LO(l))
-/* Sign-extend the given value (e) as a value (b) bits long. We cannot
- assume the HI32bits of the operand are zero, so we must perform a
- mask to ensure we can use the simple subtraction to sign-extend. */
-#define SIGNEXTEND(e,b) \
- ((unsigned_word) \
- (((e) & ((uword64) 1 << ((b) - 1))) \
- ? (((e) & (((uword64) 1 << (b)) - 1)) - ((uword64)1 << (b))) \
- : ((e) & (((((uword64) 1 << ((b) - 1)) - 1) << 1) | 1))))
-
/* 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))
fmt_unknown = 0x10000000,
fmt_uninterpreted = 0x20000000,
fmt_uninterpreted_32 = 0x40000000,
- fmt_uninterpreted_64 = 0x80000000,
+ fmt_uninterpreted_64 = 0x80000000U,
} FP_formats;
unsigned64 value_fpr PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int fpr, FP_formats));
instruction: */
#define PREVCOC1() ((STATE & simPCOC1) ? 1 : 0)
-#if 1
-#define SizeFGR() (WITH_TARGET_FLOATING_POINT_BITSIZE)
+#ifdef TARGET_ENABLE_FR
+/* FIXME: this should be enabled for all targets, but needs testing first. */
+#define SizeFGR() (((WITH_TARGET_FLOATING_POINT_BITSIZE) == 64) \
+ ? ((SR & status_FR) ? 64 : 32) \
+ : (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 SizeFGR() (WITH_TARGET_FLOATING_POINT_BITSIZE)
#endif
/* Standard FCRS bits: */
-/* Integer ALU operations: */
-
-#include "sim-alu.h"
-
-#define ALU32_END(ANS) \
- if (ALU32_HAD_OVERFLOW) \
- SignalExceptionIntegerOverflow (); \
- (ANS) = ALU32_OVERFLOW_RESULT
-
-
-#define ALU64_END(ANS) \
- if (ALU64_HAD_OVERFLOW) \
- 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),
-};
-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 */
- int hi1access;
- int lo1access;
-#define HI1ACCESS ((CPU)->r5900.hi1access)
-#define LO1ACCESS ((CPU)->r5900.lo1access)
-#if 0
-#define CHECKHILO(s) {\
- if ((HIACCESS != 0) || (LOACCESS != 0) || (HI1ACCESS != 0) || (LO1ACCESS != 0))\
- sim_io_eprintf(sd,"%s over-writing HI and LO registers values (PC = 0x%s HLPC = 0x%s)\n",(s),pr_addr(PC),pr_addr(HLPC));\
-}
-#endif
+/* HI/LO register accesses */
-} 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 DOUBLEWORDS_IN_MMI_REGS (BYTES_IN_MMI_REGS/8)
-
-#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
- TC - # of T's in the mips part of the "register"
- I - index (from 0) of desired sub part
- A - low part of "register"
- A1 - high part of register
-*/
-#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
- where <type> has two letters:
- 1 is S=signed or U=unsigned
- 2 is B=byte H=halfword W=word D=doubleword
-*/
-
-#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(&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)
+/* 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.
-#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)
+ 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;
-#define RS_SB(I) SUB_REG_SB(&rs_reg, &rs_reg1, I)
-#define RS_SH(I) SUB_REG_SH(&rs_reg, &rs_reg1, I)
-#define RS_SW(I) SUB_REG_SW(&rs_reg, &rs_reg1, I)
-#define RS_SD(I) SUB_REG_SD(&rs_reg, &rs_reg1, I)
+typedef struct _hilo_history {
+ hilo_access mt;
+ hilo_access mf;
+ hilo_access op;
+} hilo_history;
-#define RS_UB(I) SUB_REG_UB(&rs_reg, &rs_reg1, I)
-#define RS_UH(I) SUB_REG_UH(&rs_reg, &rs_reg1, I)
-#define RS_UW(I) SUB_REG_UW(&rs_reg, &rs_reg1, I)
-#define RS_UD(I) SUB_REG_UD(&rs_reg, &rs_reg1, I)
-#define RT_SB(I) SUB_REG_SB(&rt_reg, &rt_reg1, I)
-#define RT_SH(I) SUB_REG_SH(&rt_reg, &rt_reg1, I)
-#define RT_SW(I) SUB_REG_SW(&rt_reg, &rt_reg1, I)
-#define RT_SD(I) SUB_REG_SD(&rt_reg, &rt_reg1, I)
-#define RT_UB(I) SUB_REG_UB(&rt_reg, &rt_reg1, I)
-#define RT_UH(I) SUB_REG_UH(&rt_reg, &rt_reg1, I)
-#define RT_UW(I) SUB_REG_UW(&rt_reg, &rt_reg1, I)
-#define RT_UD(I) SUB_REG_UD(&rt_reg, &rt_reg1, I)
+/* Integer ALU operations: */
+#include "sim-alu.h"
-#define LO_SB(I) SUB_REG_SB(&LO, &LO1, I)
-#define LO_SH(I) SUB_REG_SH(&LO, &LO1, I)
-#define LO_SW(I) SUB_REG_SW(&LO, &LO1, I)
-#define LO_SD(I) SUB_REG_SD(&LO, &LO1, I)
+#define ALU32_END(ANS) \
+ if (ALU32_HAD_OVERFLOW) \
+ SignalExceptionIntegerOverflow (); \
+ (ANS) = (signed32) ALU32_OVERFLOW_RESULT
-#define LO_UB(I) SUB_REG_UB(&LO, &LO1, I)
-#define LO_UH(I) SUB_REG_UH(&LO, &LO1, I)
-#define LO_UW(I) SUB_REG_UW(&LO, &LO1, I)
-#define LO_UD(I) SUB_REG_UD(&LO, &LO1, I)
-#define HI_SB(I) SUB_REG_SB(&HI, &HI1, I)
-#define HI_SH(I) SUB_REG_SH(&HI, &HI1, I)
-#define HI_SW(I) SUB_REG_SW(&HI, &HI1, I)
-#define HI_SD(I) SUB_REG_SD(&HI, &HI1, I)
+#define ALU64_END(ANS) \
+ if (ALU64_HAD_OVERFLOW) \
+ SignalExceptionIntegerOverflow (); \
+ (ANS) = ALU64_OVERFLOW_RESULT;
-#define HI_UB(I) SUB_REG_UB(&HI, &HI1, I)
-#define HI_UH(I) SUB_REG_UH(&HI, &HI1, I)
-#define HI_UW(I) SUB_REG_UW(&HI, &HI1, I)
-#define HI_UD(I) SUB_REG_UD(&HI, &HI1, I)
-/* end-sanitize-r5900 */
#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_BIT ((CPU)->pending.slot_bit)
#define PENDING_SLOT_DELAY ((CPU)->pending.slot_delay)
#define PENDING_SLOT_DEST ((CPU)->pending.slot_dest)
#define PENDING_SLOT_VALUE ((CPU)->pending.slot_value)
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); \
+ sim_io_eprintf (SD, "PENDING_SCHED - 0x%lx - dest 0x%lx, val 0x%lx, bit %d, size %d, pending_in %d, pending_out %d, pending_total %d\n", \
+ (unsigned long) cia, (unsigned long) &(DEST), \
+ (unsigned long) (VAL), (BIT), (int) sizeof (DEST),\
+ 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); \
+ PENDING_IN = (PENDING_IN + 1) % PSLOTS; \
+ PENDING_TOTAL += 1; \
} while (0)
#define PENDING_WRITE(DEST,VAL,DELAY) PENDING_SCHED(DEST,VAL,DELAY,-1)
/* For backward compatibility */
#define PENDING_FILL(R,VAL) \
-{ \
+do { \
if ((R) >= FGRIDX && (R) < FGRIDX + NR_FGR) \
- PENDING_SCHED(FGR[(R) - FGRIDX], VAL, 2, -1); \
+ { \
+ PENDING_SCHED(FGR[(R) - FGRIDX], VAL, 1, -1); \
+ PENDING_SCHED(FPR_STATE[(R) - FGRIDX], fmt_uninterpreted, 1, -1); \
+ } \
else \
- PENDING_SCHED(GPR[(R)], VAL, 2, -1); \
-}
+ PENDING_SCHED(GPR[(R)], VAL, 1, -1); \
+} while (0)
+enum float_operation
+ {
+ 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
+ };
+
struct _sim_cpu {
address_word dspc; /* delay-slot PC */
#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; /* NOTE not mips16 */ \
- STATE |= simDELAYSLOT; \
- 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); \
- 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 */
#define simSIGINT (1 << 28) /* 0 = do nothing; 1 = SIGINT has occured */
#define simJALDELAYSLOT (1 << 29) /* 1 = in jal delay slot */
+#ifndef ENGINE_ISSUE_PREFIX_HOOK
#define ENGINE_ISSUE_PREFIX_HOOK() \
{ \
/* Perform any pending writes */ \
else \
STATE &= ~simPCOC0; \
}
+#endif /* ENGINE_ISSUE_PREFIX_HOOK */
/* This is nasty, since we have to rely on matching the register
#ifndef TM_MIPS_H
#define LAST_EMBED_REGNUM (89)
#define NUM_REGS (LAST_EMBED_REGNUM + 1)
-/* start-sanitize-r5900 */
-#undef NUM_REGS
-#define NUM_REGS (128)
-/* end-sanitize-r5900 */
-#endif
-
-/* 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 25
-#define FIRST_VEC_REG 25
-#define NUM_R5900_REGS 128
-#undef NUM_REGS
-#define NUM_REGS (NUM_R5900_REGS + 2*(NUM_VU_REGS) + 2*(NUM_VIF_REGS))
-#endif /* no tm-txvu.h */
#endif
-/* end-sanitize-sky */
+
/* 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 ((CPU)->registers)
#define Debug (REGISTERS[86])
#define DEPC (REGISTERS[87])
#define EPC (REGISTERS[88])
-#define COCIDX (LAST_EMBED_REGNUM + 2) /* special case : outside the normal range */
+
+ /* All internal state modified by signal_exception() that may need to be
+ rolled back for passing moment-of-exception image back to gdb. */
+ unsigned_word exc_trigger_registers[LAST_EMBED_REGNUM + 1];
+ unsigned_word exc_suspend_registers[LAST_EMBED_REGNUM + 1];
+ int exc_suspended;
+
+#define SIM_CPU_EXCEPTION_TRIGGER(SD,CPU,CIA) mips_cpu_exception_trigger(SD,CPU,CIA)
+#define SIM_CPU_EXCEPTION_SUSPEND(SD,CPU,EXC) mips_cpu_exception_suspend(SD,CPU,EXC)
+#define SIM_CPU_EXCEPTION_RESUME(SD,CPU,EXC) mips_cpu_exception_resume(SD,CPU,EXC)
unsigned_word c0_config_reg;
#define C0_CONFIG ((CPU)->c0_config_reg)
#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)
+#define COP0_BADVADDR ((unsigned32)(COP0_GPR[8]))
+
/* Keep the current format state for each register: */
FP_formats fpr_state[32];
#define FPR_STATE ((CPU)->fpr_state)
#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. */
-
- int hiaccess;
- int loaccess;
-#define HIACCESS ((CPU)->hiaccess)
-#define LOACCESS ((CPU)->loaccess)
-
-#if 0
- 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));\
-}
-#endif
+/* 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. */
-#if !defined CHECKHILO
- /* 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)
-#endif
+ hilo_history hi_history;
+#define HIHISTORY (&(CPU)->hi_history)
+ hilo_history lo_history;
+#define LOHISTORY (&(CPU)->lo_history)
- /* start-sanitize-r5900 */
- sim_r5900_cpu r5900;
+#define check_branch_bug()
+#define mark_branch_bug(TARGET)
- /* end-sanitize-r5900 */
- /* start-sanitize-vr5400 */
- /* The MDMX ISA has a very very large accumulator */
- unsigned8 acc[3 * 8];
- /* end-sanitize-vr5400 */
sim_cpu_base base;
};
#define STATE_CPU(sd,n) (&(sd)->cpu[0])
#endif
+
sim_state_base base;
};
/* TODO : these should be the bitmasks for these bits within the
status register. At the moment the following are VR4300
bit-positions: */
-#define status_KSU_mask (0x3) /* mask for KSU bits */
+#define status_KSU_mask (0x18) /* mask for KSU bits */
#define status_KSU_shift (3) /* shift for field */
#define ksu_kernel (0x0)
#define ksu_supervisor (0x1)
#define ksu_user (0x2)
#define ksu_unknown (0x3)
+#define SR_KSU ((SR & status_KSU_mask) >> status_KSU_shift)
+
#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_BEV (1 << 22) /* Location of general exception vectors */
#define status_TS (1 << 21) /* TLB shutdown has occurred */
#define status_ERL (1 << 2) /* Error level */
+#define status_IM7 (1 << 15) /* Timer Interrupt Mask */
#define status_RP (1 << 27) /* Reduced Power mode */
-/* begin-sanitize-r5900 */
-#define status_CU0 (1 << 28) /* COP0 usable */
-#define status_CU1 (1 << 29) /* COP1 usable */
-#define status_CU2 (1 << 30) /* COP2 usable */
-/* begin-sanitize-r5900 */
-#define cause_BD ((unsigned)1 << 31) /* Exception in branch delay slot */
+/* 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 */
+
+/* Status bits used by MIPS32/MIPS64. */
+#define status_UX (1 << 5) /* 64-bit user addrs */
+#define status_SX (1 << 6) /* 64-bit supervisor addrs */
+#define status_KX (1 << 7) /* 64-bit kernel addrs */
+#define status_TS (1 << 21) /* TLB shutdown has occurred */
+#define status_PX (1 << 23) /* Enable 64 bit operations */
+#define status_MX (1 << 24) /* Enable MDMX resources */
+#define status_CU0 (1 << 28) /* Coprocessor 0 usable */
+#define status_CU1 (1 << 29) /* Coprocessor 1 usable */
+#define status_CU2 (1 << 30) /* Coprocessor 2 usable */
+#define status_CU3 (1 << 31) /* Coprocessor 3 usable */
+
+#define cause_BD ((unsigned)1 << 31) /* L1 Exception in branch delay slot */
+#define cause_BD2 (1 << 30) /* L2 Exception in branch delay slot */
+#define cause_CE_mask 0x30000000 /* Coprocessor exception */
+#define cause_CE_shift 28
+#define cause_EXC2_mask 0x00070000
+#define cause_EXC2_shift 16
+#define cause_IP7 (1 << 15) /* Interrupt pending */
+#define cause_SIOP (1 << 12) /* SIO pending */
+#define cause_IP3 (1 << 11) /* Int 0 pending */
+#define cause_IP2 (1 << 10) /* Int 1 pending */
+
+#define cause_EXC_mask (0x1c) /* 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_set_EXC(x) CAUSE = (CAUSE & ~cause_EXC_mask) | ((x << cause_EXC_shift) & cause_EXC_mask)
+#define cause_set_EXC2(x) CAUSE = (CAUSE & ~cause_EXC2_mask) | ((x << cause_EXC2_shift) & cause_EXC2_mask)
+
/* 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 */
-#define UserMode ((((SR & status_KSU_mask) >> status_KSU_shift) == ksu_user) ? 1 : 0)
+#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
/* 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 DebugBreakPoint (16)
-#define Watch (23)
+enum ExceptionCause {
+ Interrupt = 0,
+ TLBModification = 1,
+ TLBLoad = 2,
+ TLBStore = 3,
+ AddressLoad = 4,
+ AddressStore = 5,
+ InstructionFetch = 6,
+ DataReference = 7,
+ SystemCall = 8,
+ BreakPoint = 9,
+ ReservedInstruction = 10,
+ CoProcessorUnusable = 11,
+ IntegerOverflow = 12, /* Arithmetic overflow (IDT monitor raises SIGFPE) */
+ Trap = 13,
+ FPE = 15,
+ DebugBreakPoint = 16, /* Impl. dep. in MIPS32/MIPS64. */
+ MDMX = 22,
+ Watch = 23,
+ MCheck = 24,
+ CacheErr = 30,
+ NMIReset = 31, /* Reserved in MIPS32/MIPS64. */
+
/* 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)
+ SimulatorFault = 0xFFFFFFFF
+};
+
+#define TLB_REFILL (0)
+#define TLB_INVALID (1)
+
+
+/* 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)
+
+
+#define BREAKPOINT_INSTRUCTION (0x0005000d)
+#define BREAKPOINT_INSTRUCTION2 (0x0000014d)
+
+
+
+void interrupt_event (SIM_DESC sd, void *data);
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, NULL_CIA, Interrupt)
+#define SignalExceptionInterrupt(level) signal_exception (SD, CPU, cia, Interrupt, level)
#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 SignalExceptionDataReference() signal_exception (SD, CPU, cia, DataReference)
#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 SignalExceptionCoProcessorUnusable(cop) signal_exception (SD, CPU, cia, CoProcessorUnusable)
+#define SignalExceptionNMIReset() signal_exception (SD, CPU, cia, NMIReset)
+#define SignalExceptionTLBRefillStore() signal_exception (SD, CPU, cia, TLBStore, TLB_REFILL)
+#define SignalExceptionTLBRefillLoad() signal_exception (SD, CPU, cia, TLBLoad, TLB_REFILL)
+#define SignalExceptionTLBInvalidStore() signal_exception (SD, CPU, cia, TLBStore, TLB_INVALID)
+#define SignalExceptionTLBInvalidLoad() signal_exception (SD, CPU, cia, TLBLoad, TLB_INVALID)
+#define SignalExceptionTLBModification() signal_exception (SD, CPU, cia, TLBModification)
+#define SignalExceptionMDMX() signal_exception (SD, CPU, cia, MDMX)
+#define SignalExceptionWatch() signal_exception (SD, CPU, cia, Watch)
+#define SignalExceptionMCheck() signal_exception (SD, CPU, cia, MCheck)
+#define SignalExceptionCacheErr() signal_exception (SD, CPU, cia, CacheErr)
/* Co-processor accesses */
+/* XXX FIXME: For now, assume that FPU (cp1) is always usable. */
+#define COP_Usable(coproc_num) (coproc_num == 1)
+
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));
#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))
+int sim_monitor (SIM_DESC sd, sim_cpu *cpu, address_word cia, unsigned int arg);
+
/* Memory accesses */
#define AccessLength_DOUBLEWORD (7)
#define AccessLength_QUADWORD (15)
-#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 Prefetch(CCA,pAddr,vAddr,DATA,hint) \
prefetch (SD, CPU, cia, CCA, pAddr, vAddr, DATA, hint)
+void unpredictable_action (sim_cpu *cpu, address_word cia);
+#define NotWordValue(val) not_word_value (SD_, (val))
+#define Unpredictable() unpredictable (SD_)
+
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_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, ...));
-FILE *tracefh;
+extern FILE *tracefh;
INLINE_SIM_MAIN (void) pending_tick PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia));
+extern SIM_CORE_SIGNAL_FN mips_core_signal;
char* pr_addr PARAMS ((SIM_ADDR addr));
char* pr_uword64 PARAMS ((uword64 addr));
+#define GPR_CLEAR(N) do { GPR_SET((N),0); } while (0)
+
+void mips_cpu_exception_trigger(SIM_DESC sd, sim_cpu* cpu, address_word pc);
+void mips_cpu_exception_suspend(SIM_DESC sd, sim_cpu* cpu, int exception);
+void mips_cpu_exception_resume(SIM_DESC sd, sim_cpu* cpu, int exception);
+
+
#if H_REVEALS_MODULE_P (SIM_MAIN_INLINE)
#include "sim-main.c"
#endif