/* 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));
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 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)
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)
+#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
+/* HI/LO register accesses */
-#define ALU64_END(ANS) \
- if (ALU64_HAD_OVERFLOW) \
- SignalExceptionIntegerOverflow (); \
- (ANS) = ALU64_OVERFLOW_RESULT;
+/* 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.
-/* start-sanitize-r5900 */
-
-#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(®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)
+ 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. */
-#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)
+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;
-#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)
-#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)
- /* 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; \
- STATE |= simDELAYSLOT; \
- delay_insn = IMEM (CIA); \
- 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)
-
+#define DELAY_SLOT(TARGET) NIA = delayslot32 (SD_, (TARGET))
+#define NULLIFY_NEXT_INSTRUCTION() NIA = nullify_next_insn32 (SD_)
/* 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
+
/* 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 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 PCIDX 37
#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 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)
+#define COP0_BADVADDR ((unsigned32)(COP0_GPR[8]))
/* Keep the current format state for each register: */
FP_formats fpr_state[32];
#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)
- /* start-sanitize-r5900 */
- int hi1access;
- int lo1access;
-#define HI1ACCESS ((CPU)->hi1access)
-#define LO1ACCESS ((CPU)->lo1access)
- /* end-sanitize-r5900 */
-#if 1
- /* The 4300 and a few other processors have interlocks on hi/lo
- register reads, and hence do not have this problem. To avoid
- spurious warnings, we just disable this always. */
-#define CHECKHILO(s)
-#else
- unsigned_word HLPC;
- /* If either of the preceding two instructions have accessed the HI
- or LO registers, then the values they see should be
- undefined. However, to keep the simulator world simple, we just
- let them use the value read and raise a warning to notify the
- user: */
-#define CHECKHILO(s) {\
- if ((HIACCESS != 0) || (LOACCESS != 0)) \
- sim_io_eprintf(sd,"%s over-writing HI and LO registers values (PC = 0x%s HLPC = 0x%s)\n",(s),pr_addr(PC),pr_addr(HLPC));\
-}
- /* 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 */
-#endif
-
-
- /* start-sanitize-r5900 */
- /* The R5900 has 128 bit registers, but the hi 64 bits are only
- touched by multimedia (MMI) instructions. The normal mips
- instructions just use the lower 64 bits. To avoid changing the
- older parts of the simulator to handle this weirdness, the high
- 64 bits of each register are kept in a separate array
- (registers1). The high 64 bits of any register are by convention
- refered by adding a '1' to the end of the normal register's name.
- So LO still refers to the low 64 bits of the LO register, LO1
- refers to the high 64 bits of that same register. */
+/* 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. */
- signed_word registers1[LAST_EMBED_REGNUM + 1];
-#define REGISTERS1 ((CPU)->registers1)
-#define GPR1 (®ISTERS1[0])
-#define LO1 (REGISTERS1[32])
-#define HI1 (REGISTERS1[33])
-#define REGISTER_SA (124)
+ hilo_history hi_history;
+#define HIHISTORY (&(CPU)->hi_history)
+ hilo_history lo_history;
+#define LOHISTORY (&(CPU)->lo_history)
- unsigned_word sa; /* the shift amount register */
-#define SA ((CPU)->sa)
+#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 */
-#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)
+
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)
-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 LOADDRMASK (WITH_TARGET_WORD_BITSIZE == 64 \
+ ? AccessLength_DOUBLEWORD /*7*/ \
+ : AccessLength_WORD /*3*/)
+#define PSIZE (WITH_TARGET_ADDRESS_BITSIZE)
+
+
+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, CPU, cia, vAddr, IorD, LorS, pAddr, CCA, raw)
-void load_memory PARAMS ((SIM_DESC sd, sim_cpu *cpu, 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, CPU, cia, memvalp, memval1p, CCA, AccessLength, pAddr, vAddr, IorD)
-void store_memory PARAMS ((SIM_DESC sd, sim_cpu *cpu, 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, CPU, cia, CCA, AccessLength, MemElem, MemElem1, pAddr, vAddr)
-void cache_op PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int op, address_word pAddr, address_word vAddr, unsigned int instruction));
+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)
-void sync_operation PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int stype));
+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))
-void prefetch PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, int CCA, address_word pAddr, address_word vAddr, int DATA, int hint));
+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)
-unsigned32 ifetch32 PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, address_word vaddr));
-#define IMEM(CIA) ifetch32 (SD, CPU, (CIA), (CIA))
+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(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, ...));
-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));
+
-void pending_tick PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia));
+#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
#endif