/* 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"
#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) \
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.
/* 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
+ hilo_history hi1_history;
+#define HI1HISTORY (&(CPU)->r5900.hi1_history)
+ hilo_history lo1_history;
+#define LO1HISTORY (&(CPU)->r5900.lo1_history)
} sim_r5900_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) \
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 */
/* 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_R5900_REGS 128
+#define NUM_CORE_REGS 128
#undef NUM_REGS
-#define NUM_REGS (NUM_R5900_REGS + 2*(NUM_VU_REGS))
+#define NUM_REGS (NUM_CORE_REGS + 2*(NUM_VU_REGS) + 2*(NUM_VIF_REGS))
#endif /* no tm-txvu.h */
-#endif
+#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
#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 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-branchbug4011 */
+#if 1
+ 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
+ /* end-sanitize-branchbug4011 */
+#define check_branch_bug()
+#define mark_branch_bug(TARGET)
+ /* start-sanitize-branchbug4011 */
+#endif
+ /* end-sanitize-branchbug4011 */
/* start-sanitize-r5900 */
sim_r5900_cpu r5900;
/* 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;
};
#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 */
-/* begin-sanitize-r5900 */
+/* start-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 */
+/* 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)
+/* 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)
+
+/* 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 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() 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 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 */
cop_sd (SD, CPU, cia, coproc_num, coproc_reg)
/* start-sanitize-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));
+#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 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));
+#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, 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));
+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))
-unsigned16 ifetch16 PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia, address_word vaddr));
-#define IMEM16(CIA,NR) ifetch16 (SD, CPU, (CIA), ((CIA) & ~1) + 2 * (NR))
+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));
+
+char* pr_addr PARAMS ((SIM_ADDR addr));
+char* pr_uword64 PARAMS ((uword64 addr));
+
+/* 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 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)
+
+/* for resume/suspend modules */
+SIM_RC sky_sim_module_install PARAMS ((SIM_DESC sd));
-void pending_tick PARAMS ((SIM_DESC sd, sim_cpu *cpu, address_word cia));
+#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 */
+};
+
+/* 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