aboutsummaryrefslogtreecommitdiff
path: root/sim/mips
diff options
context:
space:
mode:
Diffstat (limited to 'sim/mips')
-rw-r--r--sim/mips/ChangeLog34
-rw-r--r--sim/mips/interp.c279
2 files changed, 203 insertions, 110 deletions
diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog
index f74c006..3a1e213 100644
--- a/sim/mips/ChangeLog
+++ b/sim/mips/ChangeLog
@@ -1,3 +1,35 @@
+start-sanitize-r5900
+Tue Jun 3 05:00:33 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * interp.c (SignalException): Clear the simDELAYSLOT flag when an
+ exception has been taken.
+
+ * interp.c: Implement the ERET and mt/f sr instructions.
+
+Mon Jun 2 23:28:19 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * gencode.c (build_instruction): For paddu, extract unsigned
+ sub-fields.
+
+ * gencode.c (build_instruction): Saturate padds instead of padd
+ instructions.
+
+end-sanitize-r5900
+Sat May 31 00:44:16 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * interp.c (SignalException): Don't bother restarting an
+ interrupt.
+
+Fri May 30 23:41:48 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * interp.c (SignalException): Really take an interrupt.
+ (interrupt_event): Only deliver interrupts when enabled.
+
+Tue May 27 20:08:06 1997 Andrew Cagney <cagney@b1.cygnus.com>
+
+ * interp.c (sim_info): Only print info when verbose.
+ (sim_info) Use sim_io_printf for output.
+
Tue May 27 14:22:23 1997 Andrew Cagney <cagney@b1.cygnus.com>
* interp.c (CoProcPresent): Add UNUSED attribute - not used by all
@@ -192,8 +224,8 @@ Wed Feb 26 18:32:21 1997 Gavin Koch <gavin@cygnus.com>
Change values to avoid overloading DOUBLEWORD which is tested
for all insns.
* gencode.c: reinstate "offending code".
-end-sanitize-r5900
+end-sanitize-r5900
Mon Feb 24 22:47:14 1997 Dawn Perchik <dawn@cygnus.com>
* interp.c: Fix printing of addresses for non-64-bit targets.
diff --git a/sim/mips/interp.c b/sim/mips/interp.c
index b047aca..beb6288 100644
--- a/sim/mips/interp.c
+++ b/sim/mips/interp.c
@@ -385,6 +385,8 @@ static ut_reg DSPC = 0; /* delay-slot PC */
#define ksu_user (0x2)
#define ksu_unknown (0x3)
+#define status_IE (1 << 0) /* 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_SR (1 << 20) /* soft reset or NMI */
@@ -746,10 +748,18 @@ static const OPTION mips_options[] =
};
+int interrupt_pending;
+
static void
interrupt_event (SIM_DESC sd, void *data)
{
- SignalException (Interrupt);
+ if (SR & status_IE)
+ {
+ interrupt_pending = 0;
+ SignalException (Interrupt);
+ }
+ else if (!interrupt_pending)
+ sim_events_schedule (sd, 1, interrupt_event, data);
}
@@ -1240,43 +1250,49 @@ sim_info (sd,verbose)
SIM_DESC sd;
int verbose;
{
+
+ return;
/* Accessed from the GDB "info files" command: */
-
- callback->printf_filtered(callback,"MIPS %d-bit simulator\n",(PROCESSOR_64BIT ? 64 : 32));
-
- callback->printf_filtered(callback,"%s endian memory model\n",
- (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN
- ? "Big" : "Little"));
-
- callback->printf_filtered(callback,"0x%08X bytes of memory at 0x%s\n",
- STATE_MEM_SIZE (sd),
- pr_addr (STATE_MEM_BASE (sd)));
-
+ if (STATE_VERBOSE_P (sd) || verbose)
+ {
+
+ sim_io_printf (sd, "MIPS %d-bit %s endian simulator\n",
+ (PROCESSOR_64BIT ? 64 : 32),
+ (CURRENT_TARGET_BYTE_ORDER == BIG_ENDIAN ? "Big" : "Little"));
+
+ sim_io_printf (sd, "0x%08X bytes of memory at 0x%s\n",
+ STATE_MEM_SIZE (sd),
+ pr_addr (STATE_MEM_BASE (sd)));
+
#if !defined(FASTSIM)
- if (instruction_fetch_overflow != 0)
- callback->printf_filtered(callback,"Instruction fetches = 0x%08X%08X\n",instruction_fetch_overflow,instruction_fetches);
- else
- callback->printf_filtered(callback,"Instruction fetches = %d\n",instruction_fetches);
- callback->printf_filtered(callback,"Pipeline ticks = %ld\n",
- (long) sim_events_time (sd));
- /* It would be a useful feature, if when performing multi-cycle
- simulations (rather than single-stepping) we keep the start and
- end times of the execution, so that we can give a performance
- figure for the simulator. */
+#if 0
+ /* at present this simulator executes one instruction per
+ simulator cycle. Consequently this data never changes */
+ if (instruction_fetch_overflow != 0)
+ sim_io_printf (sd, "Instruction fetches = 0x%08X%08X\n",
+ instruction_fetch_overflow, instruction_fetches);
+ else
+ sim_io_printf (sd, "Instruction fetches = %d\n", instruction_fetches);
+#endif
+ /* It would be a useful feature, if when performing multi-cycle
+ simulations (rather than single-stepping) we keep the start and
+ end times of the execution, so that we can give a performance
+ figure for the simulator. */
#endif /* !FASTSIM */
-
- /* print information pertaining to MIPS ISA and architecture being simulated */
- /* things that may be interesting */
- /* instructions executed - if available */
- /* cycles executed - if available */
- /* pipeline stalls - if available */
- /* virtual time taken */
- /* profiling size */
- /* profiling frequency */
- /* profile minpc */
- /* profile maxpc */
-
- return;
+ sim_io_printf (sd, "Number of execution cycles = %ld\n",
+ (long) sim_events_time (sd));
+
+ /* print information pertaining to MIPS ISA and architecture being simulated */
+ /* things that may be interesting */
+ /* instructions executed - if available */
+ /* cycles executed - if available */
+ /* pipeline stalls - if available */
+ /* virtual time taken */
+ /* profiling size */
+ /* profiling frequency */
+ /* profile minpc */
+ /* profile maxpc */
+ }
}
SIM_RC
@@ -2731,6 +2747,7 @@ SyncOperation(stype)
static void
SignalException (int exception,...)
{
+ int vector;
SIM_DESC sd = &simulator;
/* Ensure that any active atomic read/modify/write operation will fail: */
LLBIT = 0;
@@ -2805,22 +2822,40 @@ SignalException (int exception,...)
}
}
+ /* See figure 5-17 for an outline of the code below */
+ if (! (SR & status_EXL))
+ {
+ CAUSE = (exception << 2);
+ if (state & simDELAYSLOT)
+ {
+ state &= ~simDELAYSLOT;
+ CAUSE |= cause_BD;
+ EPC = (IPC - 4); /* reference the branch instruction */
+ }
+ else
+ EPC = IPC;
+ /* FIXME: TLB et.al. */
+ vector = 0x180;
+ }
+ else
+ {
+ CAUSE = 0;
+ vector = 0x180;
+ }
+ SR |= status_EXL;
/* Store exception code into current exception id variable (used
by exit code): */
- CAUSE = (exception << 2);
- if (state & simDELAYSLOT) {
- CAUSE |= cause_BD;
- EPC = (IPC - 4); /* reference the branch instruction */
- } else
- EPC = IPC;
- /* The following is so that the simulator will continue from the
- exception address on breakpoint operations. */
- PC = EPC;
+ if (SR & status_BEV)
+ PC = (signed)0xBFC00200 + 0x180;
+ else
+ PC = (signed)0x80000000 + 0x180;
+
switch ((CAUSE >> 2) & 0x1F)
{
case Interrupt:
- sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
- sim_stopped, SIGINT);
+ /* Interrupts arrive during event processing, no need to
+ restart */
+ return;
case TLBModification:
case TLBLoad:
@@ -2829,11 +2864,15 @@ SignalException (int exception,...)
case AddressStore:
case InstructionFetch:
case DataReference:
+ /* The following is so that the simulator will continue from the
+ exception address on breakpoint operations. */
+ PC = EPC;
sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
sim_stopped, SIGBUS);
case ReservedInstruction:
case CoProcessorUnusable:
+ PC = EPC;
sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
sim_stopped, SIGILL);
@@ -2846,10 +2885,12 @@ SignalException (int exception,...)
case Watch:
case SystemCall:
case BreakPoint:
+ PC = EPC;
sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
sim_stopped, SIGTRAP);
default : /* Unknown internal exception */
+ PC = EPC;
sim_engine_halt (sd, STATE_CPU (sd, 0), NULL, NULL_CIA,
sim_stopped, SIGQUIT);
@@ -4026,85 +4067,105 @@ decode_coproc(instruction)
{
int coprocnum = ((instruction >> 26) & 3);
- switch (coprocnum) {
+ switch (coprocnum)
+ {
case 0: /* standard CPU control and cache registers */
{
- /* NOTEs:
- Standard CP0 registers
- 0 = Index R4000 VR4100 VR4300
- 1 = Random R4000 VR4100 VR4300
- 2 = EntryLo0 R4000 VR4100 VR4300
- 3 = EntryLo1 R4000 VR4100 VR4300
- 4 = Context R4000 VR4100 VR4300
- 5 = PageMask R4000 VR4100 VR4300
- 6 = Wired R4000 VR4100 VR4300
- 8 = BadVAddr R4000 VR4100 VR4300
- 9 = Count R4000 VR4100 VR4300
- 10 = EntryHi R4000 VR4100 VR4300
- 11 = Compare R4000 VR4100 VR4300
- 12 = SR R4000 VR4100 VR4300
- 13 = Cause R4000 VR4100 VR4300
- 14 = EPC R4000 VR4100 VR4300
- 15 = PRId R4000 VR4100 VR4300
- 16 = Config R4000 VR4100 VR4300
- 17 = LLAddr R4000 VR4100 VR4300
- 18 = WatchLo R4000 VR4100 VR4300
- 19 = WatchHi R4000 VR4100 VR4300
- 20 = XContext R4000 VR4100 VR4300
- 26 = PErr or ECC R4000 VR4100 VR4300
- 27 = CacheErr R4000 VR4100
- 28 = TagLo R4000 VR4100 VR4300
- 29 = TagHi R4000 VR4100 VR4300
- 30 = ErrorEPC R4000 VR4100 VR4300
- */
int code = ((instruction >> 21) & 0x1F);
/* R4000 Users Manual (second edition) lists the following CP0
instructions:
- DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000)
- DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000)
- MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000)
- MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000)
- TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001)
- TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010)
- TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110)
- TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000)
- CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii)
- ERET Exception return (VR4100 = 01000010000000000000000000011000)
- */
- if (((code == 0x00) || (code == 0x04)) && ((instruction & 0x7FF) == 0)) {
- int rt = ((instruction >> 16) & 0x1F);
-#if 0
- int rd = ((instruction >> 11) & 0x1F);
-#endif
- if (code == 0x00) { /* MF : move from */
-#if 0 /* message should be controlled by configuration option */
- callback->printf_filtered(callback,"Warning: MFC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
-#endif
- GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */
- } else { /* MT : move to */
- /* CPR[0,rd] = GPR[rt]; */
-#if 0 /* should be controlled by configuration option */
- callback->printf_filtered(callback,"Warning: MTC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
-#endif
- }
- } else
- sim_warning("Unrecognised COP0 instruction 0x%08X at IPC = 0x%s : No handler present",instruction,pr_addr(IPC));
+ DMFC0 Doubleword Move From CP0 (VR4100 = 01000000001tttttddddd00000000000)
+ DMTC0 Doubleword Move To CP0 (VR4100 = 01000000101tttttddddd00000000000)
+ MFC0 word Move From CP0 (VR4100 = 01000000000tttttddddd00000000000)
+ MTC0 word Move To CP0 (VR4100 = 01000000100tttttddddd00000000000)
+ TLBR Read Indexed TLB Entry (VR4100 = 01000010000000000000000000000001)
+ TLBWI Write Indexed TLB Entry (VR4100 = 01000010000000000000000000000010)
+ TLBWR Write Random TLB Entry (VR4100 = 01000010000000000000000000000110)
+ TLBP Probe TLB for Matching Entry (VR4100 = 01000010000000000000000000001000)
+ CACHE Cache operation (VR4100 = 101111bbbbbpppppiiiiiiiiiiiiiiii)
+ ERET Exception return (VR4100 = 01000010000000000000000000011000)
+ */
+ if (((code == 0x00) || (code == 0x04)) && ((instruction & 0x7FF) == 0))
+ {
+ int rt = ((instruction >> 16) & 0x1F);
+ int rd = ((instruction >> 11) & 0x1F);
+
+ switch (rd) /* NOTEs: Standard CP0 registers */
+ {
+ /* 0 = Index R4000 VR4100 VR4300 */
+ /* 1 = Random R4000 VR4100 VR4300 */
+ /* 2 = EntryLo0 R4000 VR4100 VR4300 */
+ /* 3 = EntryLo1 R4000 VR4100 VR4300 */
+ /* 4 = Context R4000 VR4100 VR4300 */
+ /* 5 = PageMask R4000 VR4100 VR4300 */
+ /* 6 = Wired R4000 VR4100 VR4300 */
+ /* 8 = BadVAddr R4000 VR4100 VR4300 */
+ /* 9 = Count R4000 VR4100 VR4300 */
+ /* 10 = EntryHi R4000 VR4100 VR4300 */
+ /* 11 = Compare R4000 VR4100 VR4300 */
+ /* 12 = SR R4000 VR4100 VR4300 */
+ case 12:
+ if (code == 0x00)
+ GPR[rt] = SR;
+ else
+ SR = GPR[rt];
+ break;
+ /* 13 = Cause R4000 VR4100 VR4300 */
+ /* 14 = EPC R4000 VR4100 VR4300 */
+ /* 15 = PRId R4000 VR4100 VR4300 */
+ /* 16 = Config R4000 VR4100 VR4300 */
+ /* 17 = LLAddr R4000 VR4100 VR4300 */
+ /* 18 = WatchLo R4000 VR4100 VR4300 */
+ /* 19 = WatchHi R4000 VR4100 VR4300 */
+ /* 20 = XContext R4000 VR4100 VR4300 */
+ /* 26 = PErr or ECC R4000 VR4100 VR4300 */
+ /* 27 = CacheErr R4000 VR4100 */
+ /* 28 = TagLo R4000 VR4100 VR4300 */
+ /* 29 = TagHi R4000 VR4100 VR4300 */
+ /* 30 = ErrorEPC R4000 VR4100 VR4300 */
+ GPR[rt] = 0xDEADC0DE; /* CPR[0,rd] */
+ /* CPR[0,rd] = GPR[rt]; */
+ default:
+ if (code == 0x00)
+ callback->printf_filtered(callback,"Warning: MFC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
+ else
+ callback->printf_filtered(callback,"Warning: MTC0 %d,%d not handled yet (architecture specific)\n",rt,rd);
+ }
+ }
+ else if (code == 0x10 && (instruction & 0x3f) == 0x18)
+ {
+ /* ERET */
+ if (SR & status_ERL)
+ {
+ /* Oops, not yet available */
+ callback->printf_filtered(callback,"Warning: ERET when SR[ERL] set not handled yet");
+ PC = EPC;
+ SR &= ~status_ERL;
+ }
+ else
+ {
+ PC = EPC;
+ SR &= ~status_EXL;
+ }
+ }
+ else
+ sim_warning("Unrecognised COP0 instruction 0x%08X at IPC = 0x%s : No handler present",instruction,pr_addr(IPC));
/* TODO: When executing an ERET or RFE instruction we should
clear LLBIT, to ensure that any out-standing atomic
read/modify/write sequence fails. */
}
- break;
-
+ break;
+
case 2: /* undefined co-processor */
sim_warning("COP2 instruction 0x%08X at IPC = 0x%s : No handler present",instruction,pr_addr(IPC));
break;
-
+
case 1: /* should not occur (FPU co-processor) */
case 3: /* should not occur (FPU co-processor) */
SignalException(ReservedInstruction,instruction);
break;
- }
-
+ }
+
return;
}