aboutsummaryrefslogtreecommitdiff
path: root/sim
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>1996-12-30 22:37:30 +0000
committerIan Lance Taylor <ian@airs.com>1996-12-30 22:37:30 +0000
commit7e6c297e82617a9470d22e69031892047032f759 (patch)
treee45f631886ca21098096acb5a719a3929016b74f /sim
parent60b26712521405e60cb22f162c5abc29c3cacd15 (diff)
downloadbinutils-7e6c297e82617a9470d22e69031892047032f759.zip
binutils-7e6c297e82617a9470d22e69031892047032f759.tar.gz
binutils-7e6c297e82617a9470d22e69031892047032f759.tar.bz2
* interp.c (store_word, load_word): New static functions.
(mips16_entry): New static function. (SignalException): Look for mips16 entry and exit instructions. (simulate): Use the correct index when setting fpr_state after doing a pending move.
Diffstat (limited to 'sim')
-rw-r--r--sim/mips/ChangeLog8
-rw-r--r--sim/mips/interp.c145
2 files changed, 152 insertions, 1 deletions
diff --git a/sim/mips/ChangeLog b/sim/mips/ChangeLog
index 0f7e78d..cb9e1ce 100644
--- a/sim/mips/ChangeLog
+++ b/sim/mips/ChangeLog
@@ -1,3 +1,11 @@
+Mon Dec 30 17:36:06 1996 Ian Lance Taylor <ian@cygnus.com>
+
+ * interp.c (store_word, load_word): New static functions.
+ (mips16_entry): New static function.
+ (SignalException): Look for mips16 entry and exit instructions.
+ (simulate): Use the correct index when setting fpr_state after
+ doing a pending move.
+
Sun Dec 29 09:37:18 1996 Mark Alexander <marka@cygnus.com>
* interp.c: Fix byte-swapping code throughout to work on
diff --git a/sim/mips/interp.c b/sim/mips/interp.c
index a54bfc8..ac3bed0 100644
--- a/sim/mips/interp.c
+++ b/sim/mips/interp.c
@@ -1818,6 +1818,139 @@ sim_monitor(reason)
return;
}
+/* Store a word into memory. */
+
+static void
+store_word (vaddr, val)
+ uword64 vaddr;
+ t_reg val;
+{
+ uword64 paddr;
+ int uncached;
+
+ if ((vaddr & 3) != 0)
+ SignalException (AddressStore);
+ else
+ {
+ if (AddressTranslation (vaddr, isDATA, isSTORE, &paddr, &uncached,
+ isTARGET, isREAL))
+ {
+ const uword64 mask = 7;
+ uword64 memval;
+ unsigned int byte;
+
+ paddr = (paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2));
+ byte = (vaddr & mask) ^ (BigEndianCPU << 2);
+ memval = ((uword64) val) << (8 * byte);
+ StoreMemory (uncached, AccessLength_WORD, memval, paddr, vaddr,
+ isREAL);
+ }
+ }
+}
+
+/* Load a word from memory. */
+
+static t_reg
+load_word (vaddr)
+ uword64 vaddr;
+{
+ if ((vaddr & 3) != 0)
+ SignalException (AddressLoad);
+ else
+ {
+ uword64 paddr;
+ int uncached;
+
+ if (AddressTranslation (vaddr, isDATA, isLOAD, &paddr, &uncached,
+ isTARGET, isREAL))
+ {
+ const uword64 mask = 0x7;
+ const unsigned int reverse = ReverseEndian ? 1 : 0;
+ const unsigned int bigend = BigEndianCPU ? 1 : 0;
+ uword64 memval;
+ unsigned int byte;
+
+ paddr = (paddr & ~mask) | ((paddr & mask) ^ (reverse << 2));
+ memval = LoadMemory (uncached, AccessLength_WORD, paddr, vaddr,
+ isDATA, isREAL);
+ byte = (vaddr & mask) ^ (bigend << 2);
+ return SIGNEXTEND (((memval >> (8 * byte)) & 0xffffffff), 32);
+ }
+ }
+
+ return 0;
+}
+
+/* Simulate the mips16 entry and exit pseudo-instructions. These
+ would normally be handled by the reserved instruction exception
+ code, but for ease of simulation we just handle them directly. */
+
+static void
+mips16_entry (insn)
+ unsigned int insn;
+{
+ int aregs, sregs, rreg;
+
+ aregs = (insn & 0x700) >> 8;
+ sregs = (insn & 0x0c0) >> 6;
+ rreg = (insn & 0x020) >> 5;
+
+ /* These should be checked by the caller. */
+ if (aregs == 5 || aregs == 6 || sregs == 3)
+ abort ();
+
+ if (aregs != 7)
+ {
+ int i;
+ t_reg tsp;
+
+ /* This is the entry pseudo-instruction. */
+
+ for (i = 0; i < aregs; i++)
+ store_word ((uword64) (SP + 4 * i), registers[i + 4]);
+
+ tsp = SP;
+ SP -= 32;
+
+ if (rreg)
+ {
+ tsp -= 4;
+ store_word ((uword64) tsp, RA);
+ }
+
+ for (i = 0; i < sregs; i++)
+ {
+ tsp -= 4;
+ store_word ((uword64) tsp, registers[16 + i]);
+ }
+ }
+ else
+ {
+ int i;
+ t_reg tsp;
+
+ /* This is the exit pseudo-instruction. */
+
+ tsp = SP + 32;
+
+ if (rreg)
+ {
+ tsp -= 4;
+ RA = load_word ((uword64) tsp);
+ }
+
+ for (i = 0; i < sregs; i++)
+ {
+ tsp -= 4;
+ registers[i + 16] = load_word ((uword64) tsp);
+ }
+
+ SP += 32;
+
+ PC = RA;
+ }
+}
+
void
sim_warning(char *fmt,...)
{
@@ -2566,6 +2699,16 @@ SignalException (int exception,...)
instruction was used to enter the vector (which is the
case with the current IDT monitor). */
break; /* out of the switch statement */
+ }
+ /* Look for the mips16 entry and exit instructions, and
+ simulate a handler for them. */
+ else if ((IPC & 1) != 0
+ && (instruction & 0xf81f) == 0xe809
+ && (instruction & 0x700) != 0x500
+ && (instruction & 0x700) != 0x600
+ && (instruction & 0x0c0) != 0x0c0) {
+ mips16_entry (instruction);
+ break;
} /* else fall through to normal exception processing */
sim_warning("ReservedInstruction 0x%08X at IPC = 0x%08X%08X",instruction,WORD64HI(IPC),WORD64LO(IPC));
}
@@ -4034,7 +4177,7 @@ simulate ()
registers, is when performing binary transfers. This
means we should update the register type field. */
if ((pending_slot_reg[index] >= FGRIDX) && (pending_slot_reg[index] < (FGRIDX + 32)))
- fpr_state[pending_slot_reg[index]] = fmt_uninterpreted;
+ fpr_state[pending_slot_reg[index] - FGRIDX] = fmt_uninterpreted;
#endif /* HASFPU */
}
#ifdef DEBUG