summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/arm7/arm7ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/arm7/arm7ops.c')
-rw-r--r--src/emu/cpu/arm7/arm7ops.c2342
1 files changed, 1171 insertions, 1171 deletions
diff --git a/src/emu/cpu/arm7/arm7ops.c b/src/emu/cpu/arm7/arm7ops.c
index 861eb18a2f1..63c32e4ca80 100644
--- a/src/emu/cpu/arm7/arm7ops.c
+++ b/src/emu/cpu/arm7/arm7ops.c
@@ -5,13 +5,13 @@
INLINE INT64 saturate_qbit_overflow(arm_state *cpustate, INT64 res)
{
- if (res > 2147483647) // INT32_MAX
- { // overflow high? saturate and set Q
+ if (res > 2147483647) // INT32_MAX
+ { // overflow high? saturate and set Q
res = 2147483647;
SET_CPSR(GET_CPSR | Q_MASK);
}
- else if (res < (-2147483647-1)) // INT32_MIN
- { // overflow low? saturate and set Q
+ else if (res < (-2147483647-1)) // INT32_MIN
+ { // overflow low? saturate and set Q
res = (-2147483647-1);
SET_CPSR(GET_CPSR | Q_MASK);
}
@@ -22,8 +22,8 @@ INLINE INT64 saturate_qbit_overflow(arm_state *cpustate, INT64 res)
// I could prob. convert to macro, but Switchmode shouldn't occur that often in emulated code..
void SwitchMode(arm_state *cpustate, int cpsr_mode_val)
{
- UINT32 cspr = GET_CPSR & ~MODE_FLAG;
- SET_CPSR(cspr | cpsr_mode_val);
+ UINT32 cspr = GET_CPSR & ~MODE_FLAG;
+ SET_CPSR(cspr | cpsr_mode_val);
}
@@ -47,231 +47,231 @@ void SwitchMode(arm_state *cpustate, int cpsr_mode_val)
UINT32 decodeShift(arm_state *cpustate, UINT32 insn, UINT32 *pCarry)
{
- UINT32 k = (insn & INSN_OP2_SHIFT) >> INSN_OP2_SHIFT_SHIFT; // Bits 11-7
- UINT32 rm = GET_REGISTER(cpustate, insn & INSN_OP2_RM);
- UINT32 t = (insn & INSN_OP2_SHIFT_TYPE) >> INSN_OP2_SHIFT_TYPE_SHIFT;
-
- if ((insn & INSN_OP2_RM) == 0xf) {
- // "If a register is used to specify the shift amount the PC will be 12 bytes ahead." (instead of 8)
- rm += t & 1 ? 12 : 8;
- }
-
- /* All shift types ending in 1 are Rk, not #k */
- if (t & 1)
- {
+ UINT32 k = (insn & INSN_OP2_SHIFT) >> INSN_OP2_SHIFT_SHIFT; // Bits 11-7
+ UINT32 rm = GET_REGISTER(cpustate, insn & INSN_OP2_RM);
+ UINT32 t = (insn & INSN_OP2_SHIFT_TYPE) >> INSN_OP2_SHIFT_TYPE_SHIFT;
+
+ if ((insn & INSN_OP2_RM) == 0xf) {
+ // "If a register is used to specify the shift amount the PC will be 12 bytes ahead." (instead of 8)
+ rm += t & 1 ? 12 : 8;
+ }
+
+ /* All shift types ending in 1 are Rk, not #k */
+ if (t & 1)
+ {
// LOG(("%08x: RegShift %02x %02x\n", R15, k >> 1, GET_REGISTER(cpustate, k >> 1)));
#if ARM7_DEBUG_CORE
- if ((insn & 0x80) == 0x80)
- LOG(("%08x: RegShift ERROR (p36)\n", R15));
+ if ((insn & 0x80) == 0x80)
+ LOG(("%08x: RegShift ERROR (p36)\n", R15));
#endif
- // see p35 for check on this
- //k = GET_REGISTER(cpustate, k >> 1) & 0x1f;
+ // see p35 for check on this
+ //k = GET_REGISTER(cpustate, k >> 1) & 0x1f;
- // Keep only the bottom 8 bits for a Register Shift
- k = GET_REGISTER(cpustate, k >> 1) & 0xff;
+ // Keep only the bottom 8 bits for a Register Shift
+ k = GET_REGISTER(cpustate, k >> 1) & 0xff;
- if (k == 0) /* Register shift by 0 is a no-op */
- {
+ if (k == 0) /* Register shift by 0 is a no-op */
+ {
// LOG(("%08x: NO-OP Regshift\n", R15));
- /* TODO this is wrong for at least ROR by reg with lower
- * 5 bits 0 but lower 8 bits non zero */
- if (pCarry)
- *pCarry = GET_CPSR & C_MASK;
- return rm;
- }
- }
- /* Decode the shift type and perform the shift */
- switch (t >> 1)
- {
- case 0: /* LSL */
- // LSL 32 = Result of 0, Carry = Bit 0 of RM
- // LSL >32 = Result of 0, Carry out 0
- if (k >= 32)
- {
- if (pCarry)
- *pCarry = (k == 32) ? rm & 1 : 0;
- return 0;
- }
- else
- {
- if (pCarry)
- {
- // LSL 0 = Result = RM, Carry = Old Contents of CPSR C Bit
- // LSL (0,31) = Result shifted, least significant bit is in carry out
- *pCarry = k ? (rm & (1 << (32 - k))) : (GET_CPSR & C_MASK);
- }
- return k ? LSL(rm, k) : rm;
- }
- break;
-
- case 1: /* LSR */
- if (k == 0 || k == 32)
- {
- if (pCarry)
- *pCarry = rm & SIGN_BIT;
- return 0;
- }
- else if (k > 32)
- {
- if (pCarry)
- *pCarry = 0;
- return 0;
- }
- else
- {
- if (pCarry)
- *pCarry = (rm & (1 << (k - 1)));
- return LSR(rm, k);
- }
- break;
-
- case 2: /* ASR */
- if (k == 0 || k > 32)
- k = 32;
-
- if (pCarry)
- *pCarry = (rm & (1 << (k - 1)));
- if (k >= 32)
- return rm & SIGN_BIT ? 0xffffffffu : 0;
- else
- {
- if (rm & SIGN_BIT)
- return LSR(rm, k) | (0xffffffffu << (32 - k));
- else
- return LSR(rm, k);
- }
- break;
-
- case 3: /* ROR and RRX */
- if (k)
- {
- while (k > 32)
- k -= 32;
- if (pCarry)
- *pCarry = rm & (1 << (k - 1));
- return ROR(rm, k);
- }
- else
- {
- /* RRX */
- if (pCarry)
- *pCarry = (rm & 1);
- return LSR(rm, 1) | ((GET_CPSR & C_MASK) << 2);
- }
- break;
- }
-
- LOG(("%08x: Decodeshift error\n", R15));
- return 0;
+ /* TODO this is wrong for at least ROR by reg with lower
+ * 5 bits 0 but lower 8 bits non zero */
+ if (pCarry)
+ *pCarry = GET_CPSR & C_MASK;
+ return rm;
+ }
+ }
+ /* Decode the shift type and perform the shift */
+ switch (t >> 1)
+ {
+ case 0: /* LSL */
+ // LSL 32 = Result of 0, Carry = Bit 0 of RM
+ // LSL >32 = Result of 0, Carry out 0
+ if (k >= 32)
+ {
+ if (pCarry)
+ *pCarry = (k == 32) ? rm & 1 : 0;
+ return 0;
+ }
+ else
+ {
+ if (pCarry)
+ {
+ // LSL 0 = Result = RM, Carry = Old Contents of CPSR C Bit
+ // LSL (0,31) = Result shifted, least significant bit is in carry out
+ *pCarry = k ? (rm & (1 << (32 - k))) : (GET_CPSR & C_MASK);
+ }
+ return k ? LSL(rm, k) : rm;
+ }
+ break;
+
+ case 1: /* LSR */
+ if (k == 0 || k == 32)
+ {
+ if (pCarry)
+ *pCarry = rm & SIGN_BIT;
+ return 0;
+ }
+ else if (k > 32)
+ {
+ if (pCarry)
+ *pCarry = 0;
+ return 0;
+ }
+ else
+ {
+ if (pCarry)
+ *pCarry = (rm & (1 << (k - 1)));
+ return LSR(rm, k);
+ }
+ break;
+
+ case 2: /* ASR */
+ if (k == 0 || k > 32)
+ k = 32;
+
+ if (pCarry)
+ *pCarry = (rm & (1 << (k - 1)));
+ if (k >= 32)
+ return rm & SIGN_BIT ? 0xffffffffu : 0;
+ else
+ {
+ if (rm & SIGN_BIT)
+ return LSR(rm, k) | (0xffffffffu << (32 - k));
+ else
+ return LSR(rm, k);
+ }
+ break;
+
+ case 3: /* ROR and RRX */
+ if (k)
+ {
+ while (k > 32)
+ k -= 32;
+ if (pCarry)
+ *pCarry = rm & (1 << (k - 1));
+ return ROR(rm, k);
+ }
+ else
+ {
+ /* RRX */
+ if (pCarry)
+ *pCarry = (rm & 1);
+ return LSR(rm, 1) | ((GET_CPSR & C_MASK) << 2);
+ }
+ break;
+ }
+
+ LOG(("%08x: Decodeshift error\n", R15));
+ return 0;
} /* decodeShift */
static int loadInc(arm_state *cpustate, UINT32 pat, UINT32 rbv, UINT32 s, int mode)
{
- int i, result;
- UINT32 data;
-
- result = 0;
- rbv &= ~3;
- for (i = 0; i < 16; i++)
- {
- if ((pat >> i) & 1)
- {
- if (cpustate->pendingAbtD == 0) // "Overwriting of registers stops when the abort happens."
- {
- data = READ32(rbv += 4);
- if (i == 15) {
- if (s) /* Pull full contents from stack */
- SET_MODE_REGISTER(cpustate, mode, 15, data);
- else /* Pull only address, preserve mode & status flags */
- if (MODE32)
- SET_MODE_REGISTER(cpustate, mode, 15, data);
- else
- {
- SET_MODE_REGISTER(cpustate, mode, 15, (GET_MODE_REGISTER(cpustate, mode, 15) & ~0x03FFFFFC) | (data & 0x03FFFFFC));
- }
- } else
- SET_MODE_REGISTER(cpustate, mode, i, data);
+ int i, result;
+ UINT32 data;
+
+ result = 0;
+ rbv &= ~3;
+ for (i = 0; i < 16; i++)
+ {
+ if ((pat >> i) & 1)
+ {
+ if (cpustate->pendingAbtD == 0) // "Overwriting of registers stops when the abort happens."
+ {
+ data = READ32(rbv += 4);
+ if (i == 15) {
+ if (s) /* Pull full contents from stack */
+ SET_MODE_REGISTER(cpustate, mode, 15, data);
+ else /* Pull only address, preserve mode & status flags */
+ if (MODE32)
+ SET_MODE_REGISTER(cpustate, mode, 15, data);
+ else
+ {
+ SET_MODE_REGISTER(cpustate, mode, 15, (GET_MODE_REGISTER(cpustate, mode, 15) & ~0x03FFFFFC) | (data & 0x03FFFFFC));
+ }
+ } else
+ SET_MODE_REGISTER(cpustate, mode, i, data);
}
- result++;
- }
- }
- return result;
+ result++;
+ }
+ }
+ return result;
}
static int loadDec(arm_state *cpustate, UINT32 pat, UINT32 rbv, UINT32 s, int mode)
{
- int i, result;
- UINT32 data;
-
- result = 0;
- rbv &= ~3;
- for (i = 15; i >= 0; i--)
- {
- if ((pat >> i) & 1)
- {
- if (cpustate->pendingAbtD == 0) // "Overwriting of registers stops when the abort happens."
- {
- data = READ32(rbv -= 4);
- if (i == 15) {
- if (s) /* Pull full contents from stack */
- SET_MODE_REGISTER(cpustate, mode, 15, data);
- else /* Pull only address, preserve mode & status flags */
- if (MODE32)
- SET_MODE_REGISTER(cpustate, mode, 15, data);
- else
- {
- SET_MODE_REGISTER(cpustate, mode, 15, (GET_MODE_REGISTER(cpustate, mode, 15) & ~0x03FFFFFC) | (data & 0x03FFFFFC));
- }
- }
- else
- SET_MODE_REGISTER(cpustate, mode, i, data);
- }
- result++;
- }
- }
- return result;
+ int i, result;
+ UINT32 data;
+
+ result = 0;
+ rbv &= ~3;
+ for (i = 15; i >= 0; i--)
+ {
+ if ((pat >> i) & 1)
+ {
+ if (cpustate->pendingAbtD == 0) // "Overwriting of registers stops when the abort happens."
+ {
+ data = READ32(rbv -= 4);
+ if (i == 15) {
+ if (s) /* Pull full contents from stack */
+ SET_MODE_REGISTER(cpustate, mode, 15, data);
+ else /* Pull only address, preserve mode & status flags */
+ if (MODE32)
+ SET_MODE_REGISTER(cpustate, mode, 15, data);
+ else
+ {
+ SET_MODE_REGISTER(cpustate, mode, 15, (GET_MODE_REGISTER(cpustate, mode, 15) & ~0x03FFFFFC) | (data & 0x03FFFFFC));
+ }
+ }
+ else
+ SET_MODE_REGISTER(cpustate, mode, i, data);
+ }
+ result++;
+ }
+ }
+ return result;
}
static int storeInc(arm_state *cpustate, UINT32 pat, UINT32 rbv, int mode)
{
- int i, result;
+ int i, result;
- result = 0;
- for (i = 0; i < 16; i++)
- {
- if ((pat >> i) & 1)
- {
+ result = 0;
+ for (i = 0; i < 16; i++)
+ {
+ if ((pat >> i) & 1)
+ {
#if ARM7_DEBUG_CORE
- if (i == 15) /* R15 is plus 12 from address of STM */
- LOG(("%08x: StoreInc on R15\n", R15));
+ if (i == 15) /* R15 is plus 12 from address of STM */
+ LOG(("%08x: StoreInc on R15\n", R15));
#endif
- WRITE32(rbv += 4, GET_MODE_REGISTER(cpustate, mode, i));
- result++;
- }
- }
- return result;
+ WRITE32(rbv += 4, GET_MODE_REGISTER(cpustate, mode, i));
+ result++;
+ }
+ }
+ return result;
} /* storeInc */
static int storeDec(arm_state *cpustate, UINT32 pat, UINT32 rbv, int mode)
{
- int i, result;
+ int i, result;
- result = 0;
- for (i = 15; i >= 0; i--)
- {
- if ((pat >> i) & 1)
- {
+ result = 0;
+ for (i = 15; i >= 0; i--)
+ {
+ if ((pat >> i) & 1)
+ {
#if ARM7_DEBUG_CORE
- if (i == 15) /* R15 is plus 12 from address of STM */
- LOG(("%08x: StoreDec on R15\n", R15));
+ if (i == 15) /* R15 is plus 12 from address of STM */
+ LOG(("%08x: StoreDec on R15\n", R15));
#endif
- WRITE32(rbv -= 4, GET_MODE_REGISTER(cpustate, mode, i));
- result++;
- }
- }
- return result;
+ WRITE32(rbv -= 4, GET_MODE_REGISTER(cpustate, mode, i));
+ result++;
+ }
+ }
+ return result;
} /* storeDec */
/***************************************************************************
@@ -281,41 +281,41 @@ static int storeDec(arm_state *cpustate, UINT32 pat, UINT32 rbv, int mode)
// Co-Processor Data Operation
static void HandleCoProcDO(arm_state *cpustate, UINT32 insn)
{
- // This instruction simply instructs the co-processor to do something, no data is returned to ARM7 core
- if (arm7_coproc_do_callback)
- arm7_coproc_do_callback(cpustate->device, *cpustate->program, insn, 0, 0); // simply pass entire opcode to callback - since data format is actually dependent on co-proc implementation
- else
- LOG(("%08x: Co-Processor Data Operation executed, but no callback defined!\n", R15));
+ // This instruction simply instructs the co-processor to do something, no data is returned to ARM7 core
+ if (arm7_coproc_do_callback)
+ arm7_coproc_do_callback(cpustate->device, *cpustate->program, insn, 0, 0); // simply pass entire opcode to callback - since data format is actually dependent on co-proc implementation
+ else
+ LOG(("%08x: Co-Processor Data Operation executed, but no callback defined!\n", R15));
}
// Co-Processor Register Transfer - To/From Arm to Co-Proc
static void HandleCoProcRT(arm_state *cpustate, UINT32 insn)
{
- /* xxxx 1110 oooL nnnn dddd cccc ppp1 mmmm */
-
- // Load (MRC) data from Co-Proc to ARM7 register
- if (insn & 0x00100000) // Bit 20 = Load or Store
- {
- if (arm7_coproc_rt_r_callback)
- {
- UINT32 res = arm7_coproc_rt_r_callback(cpustate->device, *cpustate->program, insn, 0); // RT Read handler must parse opcode & return appropriate result
- if (cpustate->pendingUnd == 0)
- {
- SET_REGISTER(cpustate, (insn >> 12) & 0xf, res);
- }
- }
- else
- LOG(("%08x: Co-Processor Register Transfer executed, but no RT Read callback defined!\n", R15));
- }
- // Store (MCR) data from ARM7 to Co-Proc register
- else
- {
- if (arm7_coproc_rt_w_callback)
- arm7_coproc_rt_w_callback(cpustate->device, *cpustate->program, insn, GET_REGISTER(cpustate, (insn >> 12) & 0xf), 0);
- else
- LOG(("%08x: Co-Processor Register Transfer executed, but no RT Write callback defined!\n", R15));
- }
+ /* xxxx 1110 oooL nnnn dddd cccc ppp1 mmmm */
+
+ // Load (MRC) data from Co-Proc to ARM7 register
+ if (insn & 0x00100000) // Bit 20 = Load or Store
+ {
+ if (arm7_coproc_rt_r_callback)
+ {
+ UINT32 res = arm7_coproc_rt_r_callback(cpustate->device, *cpustate->program, insn, 0); // RT Read handler must parse opcode & return appropriate result
+ if (cpustate->pendingUnd == 0)
+ {
+ SET_REGISTER(cpustate, (insn >> 12) & 0xf, res);
+ }
+ }
+ else
+ LOG(("%08x: Co-Processor Register Transfer executed, but no RT Read callback defined!\n", R15));
+ }
+ // Store (MCR) data from ARM7 to Co-Proc register
+ else
+ {
+ if (arm7_coproc_rt_w_callback)
+ arm7_coproc_rt_w_callback(cpustate->device, *cpustate->program, insn, GET_REGISTER(cpustate, (insn >> 12) & 0xf), 0);
+ else
+ LOG(("%08x: Co-Processor Register Transfer executed, but no RT Write callback defined!\n", R15));
+ }
}
/* Data Transfer - To/From Arm to Co-Proc
@@ -332,208 +332,208 @@ static void HandleCoProcRT(arm_state *cpustate, UINT32 insn)
// todo: test with valid instructions
static void HandleCoProcDT(arm_state *cpustate, UINT32 insn)
{
- UINT32 rn = (insn >> 16) & 0xf;
- UINT32 rnv = GET_REGISTER(cpustate, rn); // Get Address Value stored from Rn
- UINT32 ornv = rnv; // Keep value of Rn
- UINT32 off = (insn & 0xff) << 2; // Offset is << 2 according to manual
- UINT32 *prn = &ARM7REG(rn); // Pointer to our register, so it can be changed in the callback
-
- // Pointers to read32/write32 functions
- void (*write32)(arm_state *cpustate, UINT32 addr, UINT32 data);
- UINT32 (*read32)(arm_state *cpustate, UINT32 addr);
- write32 = PTR_WRITE32;
- read32 = PTR_READ32;
+ UINT32 rn = (insn >> 16) & 0xf;
+ UINT32 rnv = GET_REGISTER(cpustate, rn); // Get Address Value stored from Rn
+ UINT32 ornv = rnv; // Keep value of Rn
+ UINT32 off = (insn & 0xff) << 2; // Offset is << 2 according to manual
+ UINT32 *prn = &ARM7REG(rn); // Pointer to our register, so it can be changed in the callback
+
+ // Pointers to read32/write32 functions
+ void (*write32)(arm_state *cpustate, UINT32 addr, UINT32 data);
+ UINT32 (*read32)(arm_state *cpustate, UINT32 addr);
+ write32 = PTR_WRITE32;
+ read32 = PTR_READ32;
#if ARM7_DEBUG_CORE
- if (((insn >> 16) & 0xf) == 15 && (insn & 0x200000))
- LOG(("%08x: Illegal use of R15 as base for write back value!\n", R15));
+ if (((insn >> 16) & 0xf) == 15 && (insn & 0x200000))
+ LOG(("%08x: Illegal use of R15 as base for write back value!\n", R15));
#endif
- // Pre-Increment base address (IF POST INCREMENT - CALL BACK FUNCTION MUST DO IT)
- if ((insn & 0x1000000) && off)
- {
- // Up - Down bit
- if (insn & 0x800000)
- rnv += off;
- else
- rnv -= off;
- }
-
- // Load (LDC) data from ARM7 memory to Co-Proc memory
- if (insn & 0x00100000)
- {
- if (arm7_coproc_dt_r_callback)
- arm7_coproc_dt_r_callback(cpustate, insn, prn, read32);
- else
- LOG(("%08x: Co-Processer Data Transfer executed, but no READ callback defined!\n", R15));
- }
- // Store (STC) data from Co-Proc to ARM7 memory
- else
- {
- if (arm7_coproc_dt_w_callback)
- arm7_coproc_dt_w_callback(cpustate, insn, prn, write32);
- else
- LOG(("%08x: Co-Processer Data Transfer executed, but no WRITE callback defined!\n", R15));
- }
+ // Pre-Increment base address (IF POST INCREMENT - CALL BACK FUNCTION MUST DO IT)
+ if ((insn & 0x1000000) && off)
+ {
+ // Up - Down bit
+ if (insn & 0x800000)
+ rnv += off;
+ else
+ rnv -= off;
+ }
+
+ // Load (LDC) data from ARM7 memory to Co-Proc memory
+ if (insn & 0x00100000)
+ {
+ if (arm7_coproc_dt_r_callback)
+ arm7_coproc_dt_r_callback(cpustate, insn, prn, read32);
+ else
+ LOG(("%08x: Co-Processer Data Transfer executed, but no READ callback defined!\n", R15));
+ }
+ // Store (STC) data from Co-Proc to ARM7 memory
+ else
+ {
+ if (arm7_coproc_dt_w_callback)
+ arm7_coproc_dt_w_callback(cpustate, insn, prn, write32);
+ else
+ LOG(("%08x: Co-Processer Data Transfer executed, but no WRITE callback defined!\n", R15));
+ }
if (cpustate->pendingUnd != 0) return;
- // If writeback not used - ensure the original value of RN is restored in case co-proc callback changed value
- if ((insn & 0x200000) == 0)
- SET_REGISTER(cpustate, rn, ornv);
+ // If writeback not used - ensure the original value of RN is restored in case co-proc callback changed value
+ if ((insn & 0x200000) == 0)
+ SET_REGISTER(cpustate, rn, ornv);
}
INLINE void HandleBranch(arm_state *cpustate, UINT32 insn)
{
- UINT32 off = (insn & INSN_BRANCH) << 2;
-
- /* Save PC into LR if this is a branch with link */
- if (insn & INSN_BL)
- {
- SET_REGISTER(cpustate, 14, R15 + 4);
- }
-
- /* Sign-extend the 24-bit offset in our calculations */
- if (off & 0x2000000u)
- {
- if (MODE32)
- R15 -= ((~(off | 0xfc000000u)) + 1) - 8;
- else
- R15 = ((R15 - (((~(off | 0xfc000000u)) + 1) - 8)) & 0x03FFFFFC) | (R15 & ~0x03FFFFFC);
- }
- else
- {
- if (MODE32)
- R15 += off + 8;
- else
- R15 = ((R15 + (off + 8)) & 0x03FFFFFC) | (R15 & ~0x03FFFFFC);
- }
+ UINT32 off = (insn & INSN_BRANCH) << 2;
+
+ /* Save PC into LR if this is a branch with link */
+ if (insn & INSN_BL)
+ {
+ SET_REGISTER(cpustate, 14, R15 + 4);
+ }
+
+ /* Sign-extend the 24-bit offset in our calculations */
+ if (off & 0x2000000u)
+ {
+ if (MODE32)
+ R15 -= ((~(off | 0xfc000000u)) + 1) - 8;
+ else
+ R15 = ((R15 - (((~(off | 0xfc000000u)) + 1) - 8)) & 0x03FFFFFC) | (R15 & ~0x03FFFFFC);
+ }
+ else
+ {
+ if (MODE32)
+ R15 += off + 8;
+ else
+ R15 = ((R15 + (off + 8)) & 0x03FFFFFC) | (R15 & ~0x03FFFFFC);
+ }
}
static void HandleMemSingle(arm_state *cpustate, UINT32 insn)
{
- UINT32 rn, rnv, off, rd, rnv_old = 0;
-
- /* Fetch the offset */
- if (insn & INSN_I)
- {
- /* Register Shift */
- off = decodeShift(cpustate, insn, NULL);
- }
- else
- {
- /* Immediate Value */
- off = insn & INSN_SDT_IMM;
- }
-
- /* Calculate Rn, accounting for PC */
- rn = (insn & INSN_RN) >> INSN_RN_SHIFT;
-
- if (insn & INSN_SDT_P)
- {
- /* Pre-indexed addressing */
- if (insn & INSN_SDT_U)
- {
- if ((MODE32) || (rn != eR15))
- rnv = (GET_REGISTER(cpustate, rn) + off);
- else
- rnv = (GET_PC + off);
- }
- else
- {
- if ((MODE32) || (rn != eR15))
- rnv = (GET_REGISTER(cpustate, rn) - off);
+ UINT32 rn, rnv, off, rd, rnv_old = 0;
+
+ /* Fetch the offset */
+ if (insn & INSN_I)
+ {
+ /* Register Shift */
+ off = decodeShift(cpustate, insn, NULL);
+ }
+ else
+ {
+ /* Immediate Value */
+ off = insn & INSN_SDT_IMM;
+ }
+
+ /* Calculate Rn, accounting for PC */
+ rn = (insn & INSN_RN) >> INSN_RN_SHIFT;
+
+ if (insn & INSN_SDT_P)
+ {
+ /* Pre-indexed addressing */
+ if (insn & INSN_SDT_U)
+ {
+ if ((MODE32) || (rn != eR15))
+ rnv = (GET_REGISTER(cpustate, rn) + off);
else
- rnv = (GET_PC - off);
- }
-
- if (insn & INSN_SDT_W)
- {
- rnv_old = GET_REGISTER(cpustate, rn);
- SET_REGISTER(cpustate, rn, rnv);
-
- // check writeback???
- }
- else if (rn == eR15)
- {
- rnv = rnv + 8;
- }
- }
- else
- {
- /* Post-indexed addressing */
- if (rn == eR15)
- {
- if (MODE32)
- rnv = R15 + 8;
- else
- rnv = GET_PC + 8;
- }
- else
- {
- rnv = GET_REGISTER(cpustate, rn);
- }
- }
-
- /* Do the transfer */
- rd = (insn & INSN_RD) >> INSN_RD_SHIFT;
- if (insn & INSN_SDT_L)
- {
- /* Load */
- if (insn & INSN_SDT_B)
- {
- UINT32 data = READ8(rnv);
- if (cpustate->pendingAbtD == 0)
- {
- SET_REGISTER(cpustate, rd, data);
- }
- }
- else
- {
- UINT32 data = READ32(rnv);
- if (cpustate->pendingAbtD == 0)
- {
- if (rd == eR15)
- {
- if (MODE32)
- R15 = data - 4;
- else
- R15 = (R15 & ~0x03FFFFFC) /* N Z C V I F M1 M0 */ | ((data - 4) & 0x03FFFFFC);
- // LDR, PC takes 2S + 2N + 1I (5 total cycles)
- ARM7_ICOUNT -= 2;
- }
- else
- {
- SET_REGISTER(cpustate, rd, data);
- }
- }
- }
- }
- else
- {
- /* Store */
- if (insn & INSN_SDT_B)
- {
+ rnv = (GET_PC + off);
+ }
+ else
+ {
+ if ((MODE32) || (rn != eR15))
+ rnv = (GET_REGISTER(cpustate, rn) - off);
+ else
+ rnv = (GET_PC - off);
+ }
+
+ if (insn & INSN_SDT_W)
+ {
+ rnv_old = GET_REGISTER(cpustate, rn);
+ SET_REGISTER(cpustate, rn, rnv);
+
+ // check writeback???
+ }
+ else if (rn == eR15)
+ {
+ rnv = rnv + 8;
+ }
+ }
+ else
+ {
+ /* Post-indexed addressing */
+ if (rn == eR15)
+ {
+ if (MODE32)
+ rnv = R15 + 8;
+ else
+ rnv = GET_PC + 8;
+ }
+ else
+ {
+ rnv = GET_REGISTER(cpustate, rn);
+ }
+ }
+
+ /* Do the transfer */
+ rd = (insn & INSN_RD) >> INSN_RD_SHIFT;
+ if (insn & INSN_SDT_L)
+ {
+ /* Load */
+ if (insn & INSN_SDT_B)
+ {
+ UINT32 data = READ8(rnv);
+ if (cpustate->pendingAbtD == 0)
+ {
+ SET_REGISTER(cpustate, rd, data);
+ }
+ }
+ else
+ {
+ UINT32 data = READ32(rnv);
+ if (cpustate->pendingAbtD == 0)
+ {
+ if (rd == eR15)
+ {
+ if (MODE32)
+ R15 = data - 4;
+ else
+ R15 = (R15 & ~0x03FFFFFC) /* N Z C V I F M1 M0 */ | ((data - 4) & 0x03FFFFFC);
+ // LDR, PC takes 2S + 2N + 1I (5 total cycles)
+ ARM7_ICOUNT -= 2;
+ }
+ else
+ {
+ SET_REGISTER(cpustate, rd, data);
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Store */
+ if (insn & INSN_SDT_B)
+ {
#if ARM7_DEBUG_CORE
- if (rd == eR15)
- LOG(("Wrote R15 in byte mode\n"));
+ if (rd == eR15)
+ LOG(("Wrote R15 in byte mode\n"));
#endif
- WRITE8(rnv, (UINT8) GET_REGISTER(cpustate, rd) & 0xffu);
- }
- else
- {
+ WRITE8(rnv, (UINT8) GET_REGISTER(cpustate, rd) & 0xffu);
+ }
+ else
+ {
#if ARM7_DEBUG_CORE
- if (rd == eR15)
- LOG(("Wrote R15 in 32bit mode\n"));
+ if (rd == eR15)
+ LOG(("Wrote R15 in 32bit mode\n"));
#endif
- //WRITE32(rnv, rd == eR15 ? R15 + 8 : GET_REGISTER(cpustate, rd));
- WRITE32(rnv, rd == eR15 ? R15 + 8 + 4 : GET_REGISTER(cpustate, rd)); // manual says STR rd = PC, +12
- }
- // Store takes only 2 N Cycles, so add + 1
- ARM7_ICOUNT += 1;
- }
+ //WRITE32(rnv, rd == eR15 ? R15 + 8 : GET_REGISTER(cpustate, rd));
+ WRITE32(rnv, rd == eR15 ? R15 + 8 + 4 : GET_REGISTER(cpustate, rd)); // manual says STR rd = PC, +12
+ }
+ // Store takes only 2 N Cycles, so add + 1
+ ARM7_ICOUNT += 1;
+ }
if (cpustate->pendingAbtD != 0)
{
@@ -545,40 +545,40 @@ static void HandleMemSingle(arm_state *cpustate, UINT32 insn)
else
{
- /* Do post-indexing writeback */
- if (!(insn & INSN_SDT_P)/* && (insn & INSN_SDT_W)*/)
- {
- if (insn & INSN_SDT_U)
- {
- /* Writeback is applied in pipeline, before value is read from mem,
- so writeback is effectively ignored */
- if (rd == rn) {
- SET_REGISTER(cpustate, rn, GET_REGISTER(cpustate, rd));
- // todo: check for offs... ?
- }
- else {
-
- if ((insn & INSN_SDT_W) != 0)
- LOG(("%08x: RegisterWritebackIncrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0));
-
- SET_REGISTER(cpustate, rn, (rnv + off));
- }
- }
- else
- {
- /* Writeback is applied in pipeline, before value is read from mem,
- so writeback is effectively ignored */
- if (rd == rn) {
- SET_REGISTER(cpustate, rn, GET_REGISTER(cpustate, rd));
- }
- else {
- SET_REGISTER(cpustate, rn, (rnv - off));
-
- if ((insn & INSN_SDT_W) != 0)
- LOG(("%08x: RegisterWritebackDecrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0));
- }
- }
- }
+ /* Do post-indexing writeback */
+ if (!(insn & INSN_SDT_P)/* && (insn & INSN_SDT_W)*/)
+ {
+ if (insn & INSN_SDT_U)
+ {
+ /* Writeback is applied in pipeline, before value is read from mem,
+ so writeback is effectively ignored */
+ if (rd == rn) {
+ SET_REGISTER(cpustate, rn, GET_REGISTER(cpustate, rd));
+ // todo: check for offs... ?
+ }
+ else {
+
+ if ((insn & INSN_SDT_W) != 0)
+ LOG(("%08x: RegisterWritebackIncrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0));
+
+ SET_REGISTER(cpustate, rn, (rnv + off));
+ }
+ }
+ else
+ {
+ /* Writeback is applied in pipeline, before value is read from mem,
+ so writeback is effectively ignored */
+ if (rd == rn) {
+ SET_REGISTER(cpustate, rn, GET_REGISTER(cpustate, rd));
+ }
+ else {
+ SET_REGISTER(cpustate, rn, (rnv - off));
+
+ if ((insn & INSN_SDT_W) != 0)
+ LOG(("%08x: RegisterWritebackDecrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0));
+ }
+ }
+ }
}
@@ -588,169 +588,169 @@ static void HandleMemSingle(arm_state *cpustate, UINT32 insn)
static void HandleHalfWordDT(arm_state *cpustate, UINT32 insn)
{
- UINT32 rn, rnv, off, rd, rnv_old = 0;
-
- // Immediate or Register Offset?
- if (insn & 0x400000) { // Bit 22 - 1 = immediate, 0 = register
- // imm. value in high nibble (bits 8-11) and lo nibble (bit 0-3)
- off = (((insn >> 8) & 0x0f) << 4) | (insn & 0x0f);
- }
- else {
- // register
- off = GET_REGISTER(cpustate, insn & 0x0f);
- }
-
- /* Calculate Rn, accounting for PC */
- rn = (insn & INSN_RN) >> INSN_RN_SHIFT;
-
- if (insn & INSN_SDT_P)
- {
- /* Pre-indexed addressing */
- if (insn & INSN_SDT_U)
- {
- rnv = (GET_REGISTER(cpustate, rn) + off);
- }
- else
- {
- rnv = (GET_REGISTER(cpustate, rn) - off);
- }
-
- if (insn & INSN_SDT_W)
- {
- rnv_old = GET_REGISTER(cpustate, rn);
- SET_REGISTER(cpustate, rn, rnv);
-
- // check writeback???
- }
- else if (rn == eR15)
- {
- rnv = (rnv) + 8;
- }
- }
- else
- {
- /* Post-indexed addressing */
- if (rn == eR15)
- {
- rnv = R15 + 8;
- }
- else
- {
- rnv = GET_REGISTER(cpustate, rn);
- }
- }
-
- /* Do the transfer */
- rd = (insn & INSN_RD) >> INSN_RD_SHIFT;
-
- /* Load */
- if (insn & INSN_SDT_L)
- {
- // Signed?
- if (insn & 0x40)
- {
- UINT32 newval = 0;
-
- // Signed Half Word?
- if (insn & 0x20) {
- UINT16 signbyte, databyte;
- databyte = READ16(rnv) & 0xFFFF;
- signbyte = (databyte & 0x8000) ? 0xffff : 0;
- newval = (UINT32)(signbyte << 16)|databyte;
- }
- // Signed Byte
- else {
- UINT8 databyte;
- UINT32 signbyte;
- databyte = READ8(rnv) & 0xff;
- signbyte = (databyte & 0x80) ? 0xffffff : 0;
- newval = (UINT32)(signbyte << 8)|databyte;
- }
+ UINT32 rn, rnv, off, rd, rnv_old = 0;
+
+ // Immediate or Register Offset?
+ if (insn & 0x400000) { // Bit 22 - 1 = immediate, 0 = register
+ // imm. value in high nibble (bits 8-11) and lo nibble (bit 0-3)
+ off = (((insn >> 8) & 0x0f) << 4) | (insn & 0x0f);
+ }
+ else {
+ // register
+ off = GET_REGISTER(cpustate, insn & 0x0f);
+ }
+
+ /* Calculate Rn, accounting for PC */
+ rn = (insn & INSN_RN) >> INSN_RN_SHIFT;
+
+ if (insn & INSN_SDT_P)
+ {
+ /* Pre-indexed addressing */
+ if (insn & INSN_SDT_U)
+ {
+ rnv = (GET_REGISTER(cpustate, rn) + off);
+ }
+ else
+ {
+ rnv = (GET_REGISTER(cpustate, rn) - off);
+ }
+
+ if (insn & INSN_SDT_W)
+ {
+ rnv_old = GET_REGISTER(cpustate, rn);
+ SET_REGISTER(cpustate, rn, rnv);
+
+ // check writeback???
+ }
+ else if (rn == eR15)
+ {
+ rnv = (rnv) + 8;
+ }
+ }
+ else
+ {
+ /* Post-indexed addressing */
+ if (rn == eR15)
+ {
+ rnv = R15 + 8;
+ }
+ else
+ {
+ rnv = GET_REGISTER(cpustate, rn);
+ }
+ }
+
+ /* Do the transfer */
+ rd = (insn & INSN_RD) >> INSN_RD_SHIFT;
+
+ /* Load */
+ if (insn & INSN_SDT_L)
+ {
+ // Signed?
+ if (insn & 0x40)
+ {
+ UINT32 newval = 0;
+
+ // Signed Half Word?
+ if (insn & 0x20) {
+ UINT16 signbyte, databyte;
+ databyte = READ16(rnv) & 0xFFFF;
+ signbyte = (databyte & 0x8000) ? 0xffff : 0;
+ newval = (UINT32)(signbyte << 16)|databyte;
+ }
+ // Signed Byte
+ else {
+ UINT8 databyte;
+ UINT32 signbyte;
+ databyte = READ8(rnv) & 0xff;
+ signbyte = (databyte & 0x80) ? 0xffffff : 0;
+ newval = (UINT32)(signbyte << 8)|databyte;
+ }
if (cpustate->pendingAbtD == 0)
{
- // PC?
- if (rd == eR15)
- {
- R15 = newval + 8;
- // LDR(H,SH,SB) PC takes 2S + 2N + 1I (5 total cycles)
- ARM7_ICOUNT -= 2;
-
- }
- else
- {
- SET_REGISTER(cpustate, rd, newval);
- R15 += 4;
- }
-
- }
- else
- {
- R15 += 4;
- }
-
- }
- // Unsigned Half Word
- else
- {
+ // PC?
+ if (rd == eR15)
+ {
+ R15 = newval + 8;
+ // LDR(H,SH,SB) PC takes 2S + 2N + 1I (5 total cycles)
+ ARM7_ICOUNT -= 2;
+
+ }
+ else
+ {
+ SET_REGISTER(cpustate, rd, newval);
+ R15 += 4;
+ }
+
+ }
+ else
+ {
+ R15 += 4;
+ }
+
+ }
+ // Unsigned Half Word
+ else
+ {
UINT32 newval = READ16(rnv);
if (cpustate->pendingAbtD == 0)
{
- if (rd == eR15)
- {
- R15 = newval + 8;
- // extra cycles for LDR(H,SH,SB) PC (5 total cycles)
- ARM7_ICOUNT -= 2;
- }
- else
- {
- SET_REGISTER(cpustate, rd, newval);
- R15 += 4;
- }
-
- }
- else
- {
- R15 += 4;
- }
-
- }
-
-
- }
- /* Store or ARMv5+ dword insns */
- else
- {
- if ((insn & 0x60) == 0x40) // LDRD
+ if (rd == eR15)
+ {
+ R15 = newval + 8;
+ // extra cycles for LDR(H,SH,SB) PC (5 total cycles)
+ ARM7_ICOUNT -= 2;
+ }
+ else
+ {
+ SET_REGISTER(cpustate, rd, newval);
+ R15 += 4;
+ }
+
+ }
+ else
+ {
+ R15 += 4;
+ }
+
+ }
+
+
+ }
+ /* Store or ARMv5+ dword insns */
+ else
+ {
+ if ((insn & 0x60) == 0x40) // LDRD
{
SET_REGISTER(cpustate, rd, READ32(rnv));
SET_REGISTER(cpustate, rd+1, READ32(rnv+4));
- R15 += 4;
+ R15 += 4;
}
- else if ((insn & 0x60) == 0x60) // STRD
+ else if ((insn & 0x60) == 0x60) // STRD
{
WRITE32(rnv, GET_REGISTER(cpustate, rd));
WRITE32(rnv+4, GET_REGISTER(cpustate, rd+1));
- R15 += 4;
+ R15 += 4;
}
else
{
- // WRITE16(rnv, rd == eR15 ? R15 + 8 : GET_REGISTER(cpustate, rd));
- WRITE16(rnv, rd == eR15 ? R15 + 8 + 4 : GET_REGISTER(cpustate, rd)); // manual says STR RD=PC, +12 of address
+ // WRITE16(rnv, rd == eR15 ? R15 + 8 : GET_REGISTER(cpustate, rd));
+ WRITE16(rnv, rd == eR15 ? R15 + 8 + 4 : GET_REGISTER(cpustate, rd)); // manual says STR RD=PC, +12 of address
// if R15 is not increased then e.g. "STRH R10, [R15,#$10]" will be executed over and over again
#if 0
- if (rn != eR15)
+ if (rn != eR15)
#endif
- R15 += 4;
+ R15 += 4;
- // STRH takes 2 cycles, so we add + 1
- ARM7_ICOUNT += 1;
+ // STRH takes 2 cycles, so we add + 1
+ ARM7_ICOUNT += 1;
+ }
}
- }
if (cpustate->pendingAbtD != 0)
{
@@ -762,329 +762,329 @@ static void HandleHalfWordDT(arm_state *cpustate, UINT32 insn)
else
{
- // SJE: No idea if this writeback code works or makes sense here..
-
- /* Do post-indexing writeback */
- if (!(insn & INSN_SDT_P)/* && (insn & INSN_SDT_W)*/)
- {
- if (insn & INSN_SDT_U)
- {
- /* Writeback is applied in pipeline, before value is read from mem,
- so writeback is effectively ignored */
- if (rd == rn) {
- SET_REGISTER(cpustate, rn, GET_REGISTER(cpustate, rd));
- // todo: check for offs... ?
- }
- else {
-
- if ((insn & INSN_SDT_W) != 0)
- LOG(("%08x: RegisterWritebackIncrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0));
-
- SET_REGISTER(cpustate, rn, (rnv + off));
- }
- }
- else
- {
- /* Writeback is applied in pipeline, before value is read from mem,
- so writeback is effectively ignored */
- if (rd == rn) {
- SET_REGISTER(cpustate, rn, GET_REGISTER(cpustate, rd));
- }
- else {
- SET_REGISTER(cpustate, rn, (rnv - off));
-
- if ((insn & INSN_SDT_W) != 0)
- LOG(("%08x: RegisterWritebackDecrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0));
- }
- }
- }
-
- }
+ // SJE: No idea if this writeback code works or makes sense here..
+
+ /* Do post-indexing writeback */
+ if (!(insn & INSN_SDT_P)/* && (insn & INSN_SDT_W)*/)
+ {
+ if (insn & INSN_SDT_U)
+ {
+ /* Writeback is applied in pipeline, before value is read from mem,
+ so writeback is effectively ignored */
+ if (rd == rn) {
+ SET_REGISTER(cpustate, rn, GET_REGISTER(cpustate, rd));
+ // todo: check for offs... ?
+ }
+ else {
+
+ if ((insn & INSN_SDT_W) != 0)
+ LOG(("%08x: RegisterWritebackIncrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0));
+
+ SET_REGISTER(cpustate, rn, (rnv + off));
+ }
+ }
+ else
+ {
+ /* Writeback is applied in pipeline, before value is read from mem,
+ so writeback is effectively ignored */
+ if (rd == rn) {
+ SET_REGISTER(cpustate, rn, GET_REGISTER(cpustate, rd));
+ }
+ else {
+ SET_REGISTER(cpustate, rn, (rnv - off));
+
+ if ((insn & INSN_SDT_W) != 0)
+ LOG(("%08x: RegisterWritebackDecrement %d %d %d\n", R15, (insn & INSN_SDT_P) != 0, (insn & INSN_SDT_W) != 0, (insn & INSN_SDT_U) != 0));
+ }
+ }
+ }
+
+ }
}
static void HandleSwap(arm_state *cpustate, UINT32 insn)
{
- UINT32 rn, rm, rd, tmp;
+ UINT32 rn, rm, rd, tmp;
- rn = GET_REGISTER(cpustate, (insn >> 16) & 0xf); // reg. w/read address
- rm = GET_REGISTER(cpustate, insn & 0xf); // reg. w/write address
- rd = (insn >> 12) & 0xf; // dest reg
+ rn = GET_REGISTER(cpustate, (insn >> 16) & 0xf); // reg. w/read address
+ rm = GET_REGISTER(cpustate, insn & 0xf); // reg. w/write address
+ rd = (insn >> 12) & 0xf; // dest reg
#if ARM7_DEBUG_CORE
- if (rn == 15 || rm == 15 || rd == 15)
- LOG(("%08x: Illegal use of R15 in Swap Instruction\n", R15));
+ if (rn == 15 || rm == 15 || rd == 15)
+ LOG(("%08x: Illegal use of R15 in Swap Instruction\n", R15));
#endif
- // can be byte or word
- if (insn & 0x400000)
- {
- tmp = READ8(rn);
- WRITE8(rn, rm);
- SET_REGISTER(cpustate, rd, tmp);
- }
- else
- {
- tmp = READ32(rn);
- WRITE32(rn, rm);
- SET_REGISTER(cpustate, rd, tmp);
- }
-
- R15 += 4;
- // Instruction takes 1S+2N+1I cycles - so we subtract one more..
- ARM7_ICOUNT -= 1;
+ // can be byte or word
+ if (insn & 0x400000)
+ {
+ tmp = READ8(rn);
+ WRITE8(rn, rm);
+ SET_REGISTER(cpustate, rd, tmp);
+ }
+ else
+ {
+ tmp = READ32(rn);
+ WRITE32(rn, rm);
+ SET_REGISTER(cpustate, rd, tmp);
+ }
+
+ R15 += 4;
+ // Instruction takes 1S+2N+1I cycles - so we subtract one more..
+ ARM7_ICOUNT -= 1;
}
static void HandlePSRTransfer(arm_state *cpustate, UINT32 insn)
{
- int reg = (insn & 0x400000) ? SPSR : eCPSR; // Either CPSR or SPSR
- UINT32 newval, val = 0;
- int oldmode = GET_CPSR & MODE_FLAG;
-
- // get old value of CPSR/SPSR
- newval = GET_REGISTER(cpustate, reg);
-
- // MSR (bit 21 set) - Copy value to CPSR/SPSR
- if ((insn & 0x00200000))
- {
- // Immediate Value?
- if (insn & INSN_I) {
- // Value can be specified for a Right Rotate, 2x the value specified.
- int by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT;
- if (by)
- val = ROR(insn & INSN_OP2_IMM, by << 1);
- else
- val = insn & INSN_OP2_IMM;
- }
- // Value from Register
- else
- {
- val = GET_REGISTER(cpustate, insn & 0x0f);
- }
-
- // apply field code bits
- if (reg == eCPSR)
- {
- if (oldmode != eARM7_MODE_USER)
- {
- if (insn & 0x00010000)
- {
- newval = (newval & 0xffffff00) | (val & 0x000000ff);
- }
- if (insn & 0x00020000)
- {
- newval = (newval & 0xffff00ff) | (val & 0x0000ff00);
- }
- if (insn & 0x00040000)
- {
- newval = (newval & 0xff00ffff) | (val & 0x00ff0000);
- }
- }
-
- // status flags can be modified regardless of mode
- if (insn & 0x00080000)
- {
- // TODO for non ARMv5E mask should be 0xf0000000 (ie mask Q bit)
- newval = (newval & 0x00ffffff) | (val & 0xf8000000);
- }
- }
- else // SPSR has stricter requirements
- {
- if (((GET_CPSR & 0x1f) > 0x10) && ((GET_CPSR & 0x1f) < 0x1f))
- {
- if (insn & 0x00010000)
- {
- newval = (newval & 0xffffff00) | (val & 0xff);
- }
- if (insn & 0x00020000)
- {
- newval = (newval & 0xffff00ff) | (val & 0xff00);
- }
- if (insn & 0x00040000)
- {
- newval = (newval & 0xff00ffff) | (val & 0xff0000);
- }
- if (insn & 0x00080000)
- {
- // TODO for non ARMv5E mask should be 0xf0000000 (ie mask Q bit)
- newval = (newval & 0x00ffffff) | (val & 0xf8000000);
- }
- }
- }
+ int reg = (insn & 0x400000) ? SPSR : eCPSR; // Either CPSR or SPSR
+ UINT32 newval, val = 0;
+ int oldmode = GET_CPSR & MODE_FLAG;
+
+ // get old value of CPSR/SPSR
+ newval = GET_REGISTER(cpustate, reg);
+
+ // MSR (bit 21 set) - Copy value to CPSR/SPSR
+ if ((insn & 0x00200000))
+ {
+ // Immediate Value?
+ if (insn & INSN_I) {
+ // Value can be specified for a Right Rotate, 2x the value specified.
+ int by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT;
+ if (by)
+ val = ROR(insn & INSN_OP2_IMM, by << 1);
+ else
+ val = insn & INSN_OP2_IMM;
+ }
+ // Value from Register
+ else
+ {
+ val = GET_REGISTER(cpustate, insn & 0x0f);
+ }
+
+ // apply field code bits
+ if (reg == eCPSR)
+ {
+ if (oldmode != eARM7_MODE_USER)
+ {
+ if (insn & 0x00010000)
+ {
+ newval = (newval & 0xffffff00) | (val & 0x000000ff);
+ }
+ if (insn & 0x00020000)
+ {
+ newval = (newval & 0xffff00ff) | (val & 0x0000ff00);
+ }
+ if (insn & 0x00040000)
+ {
+ newval = (newval & 0xff00ffff) | (val & 0x00ff0000);
+ }
+ }
+
+ // status flags can be modified regardless of mode
+ if (insn & 0x00080000)
+ {
+ // TODO for non ARMv5E mask should be 0xf0000000 (ie mask Q bit)
+ newval = (newval & 0x00ffffff) | (val & 0xf8000000);
+ }
+ }
+ else // SPSR has stricter requirements
+ {
+ if (((GET_CPSR & 0x1f) > 0x10) && ((GET_CPSR & 0x1f) < 0x1f))
+ {
+ if (insn & 0x00010000)
+ {
+ newval = (newval & 0xffffff00) | (val & 0xff);
+ }
+ if (insn & 0x00020000)
+ {
+ newval = (newval & 0xffff00ff) | (val & 0xff00);
+ }
+ if (insn & 0x00040000)
+ {
+ newval = (newval & 0xff00ffff) | (val & 0xff0000);
+ }
+ if (insn & 0x00080000)
+ {
+ // TODO for non ARMv5E mask should be 0xf0000000 (ie mask Q bit)
+ newval = (newval & 0x00ffffff) | (val & 0xf8000000);
+ }
+ }
+ }
#if 0
- // force valid mode
- newval |= 0x10;
+ // force valid mode
+ newval |= 0x10;
#endif
- // Update the Register
- if (reg == eCPSR)
- SET_CPSR(newval);
- else
- SET_REGISTER(cpustate, reg, newval);
-
- // Switch to new mode if changed
- if ((newval & MODE_FLAG) != oldmode)
- SwitchMode(cpustate, GET_MODE);
-
- }
- // MRS (bit 21 clear) - Copy CPSR or SPSR to specified Register
- else
- {
- SET_REGISTER(cpustate, (insn >> 12)& 0x0f, GET_REGISTER(cpustate, reg));
- }
+ // Update the Register
+ if (reg == eCPSR)
+ SET_CPSR(newval);
+ else
+ SET_REGISTER(cpustate, reg, newval);
+
+ // Switch to new mode if changed
+ if ((newval & MODE_FLAG) != oldmode)
+ SwitchMode(cpustate, GET_MODE);
+
+ }
+ // MRS (bit 21 clear) - Copy CPSR or SPSR to specified Register
+ else
+ {
+ SET_REGISTER(cpustate, (insn >> 12)& 0x0f, GET_REGISTER(cpustate, reg));
+ }
}
static void HandleALU(arm_state *cpustate, UINT32 insn)
{
- UINT32 op2, sc = 0, rd, rn, opcode;
- UINT32 by, rdn;
+ UINT32 op2, sc = 0, rd, rn, opcode;
+ UINT32 by, rdn;
// Normal Data Processing : 1S
// Data Processing with register specified shift : 1S + 1I
// Data Processing with PC written : 2S + 1N
// Data Processing with register specified shift and PC written : 2S + 1N + 1I
- opcode = (insn & INSN_OPCODE) >> INSN_OPCODE_SHIFT;
-
- rd = 0;
- rn = 0;
-
- /* --------------*/
- /* Construct Op2 */
- /* --------------*/
-
- /* Immediate constant */
- if (insn & INSN_I)
- {
- by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT;
- if (by)
- {
- op2 = ROR(insn & INSN_OP2_IMM, by << 1);
- sc = op2 & SIGN_BIT;
- }
- else
- {
- op2 = insn & INSN_OP2; // SJE: Shouldn't this be INSN_OP2_IMM?
- sc = GET_CPSR & C_MASK;
- }
- }
- /* Op2 = Register Value */
- else
- {
- op2 = decodeShift(cpustate, insn, (insn & INSN_S) ? &sc : NULL);
-
- // LD TODO sc will always be 0 if this applies
- if (!(insn & INSN_S))
- sc = 0;
-
- // extra cycle (register specified shift)
- ARM7_ICOUNT -= 1;
- }
-
- // LD TODO this comment is wrong
- /* Calculate Rn to account for pipelining */
- if ((opcode & 0xd) != 0xd) /* No Rn in MOV */
- {
- if ((rn = (insn & INSN_RN) >> INSN_RN_SHIFT) == eR15)
- {
+ opcode = (insn & INSN_OPCODE) >> INSN_OPCODE_SHIFT;
+
+ rd = 0;
+ rn = 0;
+
+ /* --------------*/
+ /* Construct Op2 */
+ /* --------------*/
+
+ /* Immediate constant */
+ if (insn & INSN_I)
+ {
+ by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT;
+ if (by)
+ {
+ op2 = ROR(insn & INSN_OP2_IMM, by << 1);
+ sc = op2 & SIGN_BIT;
+ }
+ else
+ {
+ op2 = insn & INSN_OP2; // SJE: Shouldn't this be INSN_OP2_IMM?
+ sc = GET_CPSR & C_MASK;
+ }
+ }
+ /* Op2 = Register Value */
+ else
+ {
+ op2 = decodeShift(cpustate, insn, (insn & INSN_S) ? &sc : NULL);
+
+ // LD TODO sc will always be 0 if this applies
+ if (!(insn & INSN_S))
+ sc = 0;
+
+ // extra cycle (register specified shift)
+ ARM7_ICOUNT -= 1;
+ }
+
+ // LD TODO this comment is wrong
+ /* Calculate Rn to account for pipelining */
+ if ((opcode & 0xd) != 0xd) /* No Rn in MOV */
+ {
+ if ((rn = (insn & INSN_RN) >> INSN_RN_SHIFT) == eR15)
+ {
#if ARM7_DEBUG_CORE
- LOG(("%08x: Pipelined R15 (Shift %d)\n", R15, (insn & INSN_I ? 8 : insn & 0x10u ? 12 : 12)));
+ LOG(("%08x: Pipelined R15 (Shift %d)\n", R15, (insn & INSN_I ? 8 : insn & 0x10u ? 12 : 12)));
#endif
if (MODE32)
- rn = R15 + 8;
- else
- rn = GET_PC + 8;
- }
- else
- {
- rn = GET_REGISTER(cpustate, rn);
- }
- }
-
- /* Perform the operation */
-
- switch (opcode)
- {
- /* Arithmetic operations */
- case OPCODE_SBC:
- rd = (rn - op2 - (GET_CPSR & C_MASK ? 0 : 1));
- HandleALUSubFlags(rd, rn, op2);
- break;
- case OPCODE_CMP:
- case OPCODE_SUB:
- rd = (rn - op2);
- HandleALUSubFlags(rd, rn, op2);
- break;
- case OPCODE_RSC:
- rd = (op2 - rn - (GET_CPSR & C_MASK ? 0 : 1));
- HandleALUSubFlags(rd, op2, rn);
- break;
- case OPCODE_RSB:
- rd = (op2 - rn);
- HandleALUSubFlags(rd, op2, rn);
- break;
- case OPCODE_ADC:
- rd = (rn + op2 + ((GET_CPSR & C_MASK) >> C_BIT));
- HandleALUAddFlags(rd, rn, op2);
- break;
- case OPCODE_CMN:
- case OPCODE_ADD:
- rd = (rn + op2);
- HandleALUAddFlags(rd, rn, op2);
- break;
-
- /* Logical operations */
- case OPCODE_AND:
- case OPCODE_TST:
- rd = rn & op2;
- HandleALULogicalFlags(rd, sc);
- break;
- case OPCODE_BIC:
- rd = rn & ~op2;
- HandleALULogicalFlags(rd, sc);
- break;
- case OPCODE_TEQ:
- case OPCODE_EOR:
- rd = rn ^ op2;
- HandleALULogicalFlags(rd, sc);
- break;
- case OPCODE_ORR:
- rd = rn | op2;
- HandleALULogicalFlags(rd, sc);
- break;
- case OPCODE_MOV:
- rd = op2;
- HandleALULogicalFlags(rd, sc);
- break;
- case OPCODE_MVN:
- rd = (~op2);
- HandleALULogicalFlags(rd, sc);
- break;
- }
-
- /* Put the result in its register if not one of the test only opcodes (TST,TEQ,CMP,CMN) */
- rdn = (insn & INSN_RD) >> INSN_RD_SHIFT;
- if ((opcode & 0xc) != 0x8)
- {
- // If Rd = R15, but S Flag not set, Result is placed in R15, but CPSR is not affected (page 44)
- if (rdn == eR15 && !(insn & INSN_S))
- {
+ rn = R15 + 8;
+ else
+ rn = GET_PC + 8;
+ }
+ else
+ {
+ rn = GET_REGISTER(cpustate, rn);
+ }
+ }
+
+ /* Perform the operation */
+
+ switch (opcode)
+ {
+ /* Arithmetic operations */
+ case OPCODE_SBC:
+ rd = (rn - op2 - (GET_CPSR & C_MASK ? 0 : 1));
+ HandleALUSubFlags(rd, rn, op2);
+ break;
+ case OPCODE_CMP:
+ case OPCODE_SUB:
+ rd = (rn - op2);
+ HandleALUSubFlags(rd, rn, op2);
+ break;
+ case OPCODE_RSC:
+ rd = (op2 - rn - (GET_CPSR & C_MASK ? 0 : 1));
+ HandleALUSubFlags(rd, op2, rn);
+ break;
+ case OPCODE_RSB:
+ rd = (op2 - rn);
+ HandleALUSubFlags(rd, op2, rn);
+ break;
+ case OPCODE_ADC:
+ rd = (rn + op2 + ((GET_CPSR & C_MASK) >> C_BIT));
+ HandleALUAddFlags(rd, rn, op2);
+ break;
+ case OPCODE_CMN:
+ case OPCODE_ADD:
+ rd = (rn + op2);
+ HandleALUAddFlags(rd, rn, op2);
+ break;
+
+ /* Logical operations */
+ case OPCODE_AND:
+ case OPCODE_TST:
+ rd = rn & op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_BIC:
+ rd = rn & ~op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_TEQ:
+ case OPCODE_EOR:
+ rd = rn ^ op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_ORR:
+ rd = rn | op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_MOV:
+ rd = op2;
+ HandleALULogicalFlags(rd, sc);
+ break;
+ case OPCODE_MVN:
+ rd = (~op2);
+ HandleALULogicalFlags(rd, sc);
+ break;
+ }
+
+ /* Put the result in its register if not one of the test only opcodes (TST,TEQ,CMP,CMN) */
+ rdn = (insn & INSN_RD) >> INSN_RD_SHIFT;
+ if ((opcode & 0xc) != 0x8)
+ {
+ // If Rd = R15, but S Flag not set, Result is placed in R15, but CPSR is not affected (page 44)
+ if (rdn == eR15 && !(insn & INSN_S))
+ {
if (MODE32)
{
- R15 = rd;
- }
- else
- {
- R15 = (R15 & ~0x03FFFFFC) | (rd & 0x03FFFFFC);
- }
- // extra cycles (PC written)
- ARM7_ICOUNT -= 2;
- }
- else
- {
- // Rd = 15 and S Flag IS set, Result is placed in R15, and current mode SPSR moved to CPSR
- if (rdn == eR15) {
+ R15 = rd;
+ }
+ else
+ {
+ R15 = (R15 & ~0x03FFFFFC) | (rd & 0x03FFFFFC);
+ }
+ // extra cycles (PC written)
+ ARM7_ICOUNT -= 2;
+ }
+ else
+ {
+ // Rd = 15 and S Flag IS set, Result is placed in R15, and current mode SPSR moved to CPSR
+ if (rdn == eR15) {
if (MODE32)
{
@@ -1094,73 +1094,73 @@ static void HandleALU(arm_state *cpustate, UINT32 insn)
if (GET_MODE != eARM7_MODE_USER)
{
- // Update CPSR from SPSR
- SET_CPSR(GET_REGISTER(cpustate, SPSR));
- SwitchMode(cpustate, GET_MODE);
- }
+ // Update CPSR from SPSR
+ SET_CPSR(GET_REGISTER(cpustate, SPSR));
+ SwitchMode(cpustate, GET_MODE);
+ }
- R15 = rd;
+ R15 = rd;
- }
- else
- {
- UINT32 temp;
+ }
+ else
+ {
+ UINT32 temp;
R15 = rd; //(R15 & 0x03FFFFFC) | (rd & 0xFC000003);
temp = (GET_CPSR & 0x0FFFFF20) | (rd & 0xF0000000) /* N Z C V */ | ((rd & 0x0C000000) >> (26 - 6)) /* I F */ | (rd & 0x00000003) /* M1 M0 */;
SET_CPSR( temp);
SwitchMode( cpustate, temp & 3);
- }
+ }
- // extra cycles (PC written)
- ARM7_ICOUNT -= 2;
+ // extra cycles (PC written)
+ ARM7_ICOUNT -= 2;
- /* IRQ masks may have changed in this instruction */
+ /* IRQ masks may have changed in this instruction */
// ARM7_CHECKIRQ;
- }
- else
- /* S Flag is set - Write results to register & update CPSR (which was already handled using HandleALU flag macros) */
- SET_REGISTER(cpustate, rdn, rd);
- }
- }
- // SJE: Don't think this applies any more.. (see page 44 at bottom)
- /* TST & TEQ can affect R15 (the condition code register) with the S bit set */
- else if (rdn == eR15)
- {
- if (insn & INSN_S) {
+ }
+ else
+ /* S Flag is set - Write results to register & update CPSR (which was already handled using HandleALU flag macros) */
+ SET_REGISTER(cpustate, rdn, rd);
+ }
+ }
+ // SJE: Don't think this applies any more.. (see page 44 at bottom)
+ /* TST & TEQ can affect R15 (the condition code register) with the S bit set */
+ else if (rdn == eR15)
+ {
+ if (insn & INSN_S) {
#if ARM7_DEBUG_CORE
- LOG(("%08x: TST class on R15 s bit set\n", R15));
+ LOG(("%08x: TST class on R15 s bit set\n", R15));
#endif
if (MODE32)
- R15 = rd;
- else
- {
- UINT32 temp;
+ R15 = rd;
+ else
+ {
+ UINT32 temp;
R15 = (R15 & 0x03FFFFFC) | (rd & ~0x03FFFFFC);
temp = (GET_CPSR & 0x0FFFFF20) | (rd & 0xF0000000) /* N Z C V */ | ((rd & 0x0C000000) >> (26 - 6)) /* I F */ | (rd & 0x00000003) /* M1 M0 */;
SET_CPSR( temp);
SwitchMode( cpustate, temp & 3);
}
- /* IRQ masks may have changed in this instruction */
+ /* IRQ masks may have changed in this instruction */
// ARM7_CHECKIRQ;
- }
- else
- {
+ }
+ else
+ {
#if ARM7_DEBUG_CORE
- LOG(("%08x: TST class on R15 no s bit set\n", R15));
+ LOG(("%08x: TST class on R15 no s bit set\n", R15));
#endif
- }
- // extra cycles (PC written)
- ARM7_ICOUNT -= 2;
- }
+ }
+ // extra cycles (PC written)
+ ARM7_ICOUNT -= 2;
+ }
- // compensate for the -3 at the end
- ARM7_ICOUNT += 2;
+ // compensate for the -3 at the end
+ ARM7_ICOUNT += 2;
}
static void HandleMul(arm_state *cpustate, UINT32 insn)
{
- UINT32 r, rm, rs;
+ UINT32 r, rm, rs;
// MUL takes 1S + mI and MLA 1S + (m+1)I cycles to execute, where S and I are as
// defined in 6.2 Cycle Types on page 6-2.
@@ -1171,32 +1171,32 @@ static void HandleMul(arm_state *cpustate, UINT32 insn)
rm = GET_REGISTER(cpustate, insn & INSN_MUL_RM);
rs = GET_REGISTER(cpustate, (insn & INSN_MUL_RS) >> INSN_MUL_RS_SHIFT);
- /* Do the basic multiply of Rm and Rs */
- r = rm * rs;
+ /* Do the basic multiply of Rm and Rs */
+ r = rm * rs;
#if ARM7_DEBUG_CORE
- if ((insn & INSN_MUL_RM) == 0xf ||
- ((insn & INSN_MUL_RS) >> INSN_MUL_RS_SHIFT) == 0xf ||
- ((insn & INSN_MUL_RN) >> INSN_MUL_RN_SHIFT) == 0xf)
- LOG(("%08x: R15 used in mult\n", R15));
+ if ((insn & INSN_MUL_RM) == 0xf ||
+ ((insn & INSN_MUL_RS) >> INSN_MUL_RS_SHIFT) == 0xf ||
+ ((insn & INSN_MUL_RN) >> INSN_MUL_RN_SHIFT) == 0xf)
+ LOG(("%08x: R15 used in mult\n", R15));
#endif
- /* Add on Rn if this is a MLA */
- if (insn & INSN_MUL_A)
- {
- r += GET_REGISTER(cpustate, (insn & INSN_MUL_RN) >> INSN_MUL_RN_SHIFT);
- // extra cycle for MLA
+ /* Add on Rn if this is a MLA */
+ if (insn & INSN_MUL_A)
+ {
+ r += GET_REGISTER(cpustate, (insn & INSN_MUL_RN) >> INSN_MUL_RN_SHIFT);
+ // extra cycle for MLA
ARM7_ICOUNT -= 1;
- }
+ }
- /* Write the result */
- SET_REGISTER(cpustate, (insn & INSN_MUL_RD) >> INSN_MUL_RD_SHIFT, r);
+ /* Write the result */
+ SET_REGISTER(cpustate, (insn & INSN_MUL_RD) >> INSN_MUL_RD_SHIFT, r);
- /* Set N and Z if asked */
- if (insn & INSN_S)
- {
- SET_CPSR((GET_CPSR & ~(N_MASK | Z_MASK)) | HandleALUNZFlags(r));
- }
+ /* Set N and Z if asked */
+ if (insn & INSN_S)
+ {
+ SET_CPSR((GET_CPSR & ~(N_MASK | Z_MASK)) | HandleALUNZFlags(r));
+ }
if (rs & SIGN_BIT) rs = -rs;
if (rs < 0x00000100) ARM7_ICOUNT -= 1 + 1;
@@ -1210,45 +1210,45 @@ static void HandleMul(arm_state *cpustate, UINT32 insn)
// todo: add proper cycle counts
static void HandleSMulLong(arm_state *cpustate, UINT32 insn)
{
- INT32 rm, rs;
- UINT32 rhi, rlo;
- INT64 res = 0;
+ INT32 rm, rs;
+ UINT32 rhi, rlo;
+ INT64 res = 0;
// MULL takes 1S + (m+1)I and MLAL 1S + (m+2)I cycles to execute, where m is the
// number of 8 bit multiplier array cycles required to complete the multiply, which is
// controlled by the value of the multiplier operand specified by Rs.
- rm = (INT32)GET_REGISTER(cpustate, insn & 0xf);
- rs = (INT32)GET_REGISTER(cpustate, ((insn >> 8) & 0xf));
- rhi = (insn >> 16) & 0xf;
- rlo = (insn >> 12) & 0xf;
+ rm = (INT32)GET_REGISTER(cpustate, insn & 0xf);
+ rs = (INT32)GET_REGISTER(cpustate, ((insn >> 8) & 0xf));
+ rhi = (insn >> 16) & 0xf;
+ rlo = (insn >> 12) & 0xf;
#if ARM7_DEBUG_CORE
- if ((insn & 0xf) == 15 || ((insn >> 8) & 0xf) == 15 || ((insn >> 16) & 0xf) == 15 || ((insn >> 12) & 0xf) == 15)
- LOG(("%08x: Illegal use of PC as a register in SMULL opcode\n", R15));
+ if ((insn & 0xf) == 15 || ((insn >> 8) & 0xf) == 15 || ((insn >> 16) & 0xf) == 15 || ((insn >> 12) & 0xf) == 15)
+ LOG(("%08x: Illegal use of PC as a register in SMULL opcode\n", R15));
#endif
- /* Perform the multiplication */
- res = (INT64)rm * rs;
+ /* Perform the multiplication */
+ res = (INT64)rm * rs;
- /* Add on Rn if this is a MLA */
- if (insn & INSN_MUL_A)
- {
- INT64 acum = (INT64)((((INT64)(GET_REGISTER(cpustate, rhi))) << 32) | GET_REGISTER(cpustate, rlo));
- res += acum;
- // extra cycle for MLA
+ /* Add on Rn if this is a MLA */
+ if (insn & INSN_MUL_A)
+ {
+ INT64 acum = (INT64)((((INT64)(GET_REGISTER(cpustate, rhi))) << 32) | GET_REGISTER(cpustate, rlo));
+ res += acum;
+ // extra cycle for MLA
ARM7_ICOUNT -= 1;
- }
+ }
- /* Write the result (upper dword goes to RHi, lower to RLo) */
- SET_REGISTER(cpustate, rhi, res >> 32);
- SET_REGISTER(cpustate, rlo, res & 0xFFFFFFFF);
+ /* Write the result (upper dword goes to RHi, lower to RLo) */
+ SET_REGISTER(cpustate, rhi, res >> 32);
+ SET_REGISTER(cpustate, rlo, res & 0xFFFFFFFF);
- /* Set N and Z if asked */
- if (insn & INSN_S)
- {
- SET_CPSR((GET_CPSR & ~(N_MASK | Z_MASK)) | HandleLongALUNZFlags(res));
- }
+ /* Set N and Z if asked */
+ if (insn & INSN_S)
+ {
+ SET_CPSR((GET_CPSR & ~(N_MASK | Z_MASK)) | HandleLongALUNZFlags(res));
+ }
if (rs < 0) rs = -rs;
if (rs < 0x00000100) ARM7_ICOUNT -= 1 + 1 + 1;
@@ -1262,45 +1262,45 @@ static void HandleSMulLong(arm_state *cpustate, UINT32 insn)
// todo: add proper cycle counts
static void HandleUMulLong(arm_state *cpustate, UINT32 insn)
{
- UINT32 rm, rs;
- UINT32 rhi, rlo;
- UINT64 res = 0;
+ UINT32 rm, rs;
+ UINT32 rhi, rlo;
+ UINT64 res = 0;
// MULL takes 1S + (m+1)I and MLAL 1S + (m+2)I cycles to execute, where m is the
// number of 8 bit multiplier array cycles required to complete the multiply, which is
// controlled by the value of the multiplier operand specified by Rs.
- rm = (INT32)GET_REGISTER(cpustate, insn & 0xf);
- rs = (INT32)GET_REGISTER(cpustate, ((insn >> 8) & 0xf));
- rhi = (insn >> 16) & 0xf;
- rlo = (insn >> 12) & 0xf;
+ rm = (INT32)GET_REGISTER(cpustate, insn & 0xf);
+ rs = (INT32)GET_REGISTER(cpustate, ((insn >> 8) & 0xf));
+ rhi = (insn >> 16) & 0xf;
+ rlo = (insn >> 12) & 0xf;
#if ARM7_DEBUG_CORE
- if (((insn & 0xf) == 15) || (((insn >> 8) & 0xf) == 15) || (((insn >> 16) & 0xf) == 15) || (((insn >> 12) & 0xf) == 15))
- LOG(("%08x: Illegal use of PC as a register in SMULL opcode\n", R15));
+ if (((insn & 0xf) == 15) || (((insn >> 8) & 0xf) == 15) || (((insn >> 16) & 0xf) == 15) || (((insn >> 12) & 0xf) == 15))
+ LOG(("%08x: Illegal use of PC as a register in SMULL opcode\n", R15));
#endif
- /* Perform the multiplication */
- res = (UINT64)rm * rs;
+ /* Perform the multiplication */
+ res = (UINT64)rm * rs;
- /* Add on Rn if this is a MLA */
- if (insn & INSN_MUL_A)
- {
- UINT64 acum = (UINT64)((((UINT64)(GET_REGISTER(cpustate, rhi))) << 32) | GET_REGISTER(cpustate, rlo));
- res += acum;
- // extra cycle for MLA
+ /* Add on Rn if this is a MLA */
+ if (insn & INSN_MUL_A)
+ {
+ UINT64 acum = (UINT64)((((UINT64)(GET_REGISTER(cpustate, rhi))) << 32) | GET_REGISTER(cpustate, rlo));
+ res += acum;
+ // extra cycle for MLA
ARM7_ICOUNT -= 1;
- }
+ }
- /* Write the result (upper dword goes to RHi, lower to RLo) */
- SET_REGISTER(cpustate, rhi, res >> 32);
- SET_REGISTER(cpustate, rlo, res & 0xFFFFFFFF);
+ /* Write the result (upper dword goes to RHi, lower to RLo) */
+ SET_REGISTER(cpustate, rhi, res >> 32);
+ SET_REGISTER(cpustate, rlo, res & 0xFFFFFFFF);
- /* Set N and Z if asked */
- if (insn & INSN_S)
- {
- SET_CPSR((GET_CPSR & ~(N_MASK | Z_MASK)) | HandleLongALUNZFlags(res));
- }
+ /* Set N and Z if asked */
+ if (insn & INSN_S)
+ {
+ SET_CPSR((GET_CPSR & ~(N_MASK | Z_MASK)) | HandleLongALUNZFlags(res));
+ }
if (rs < 0x00000100) ARM7_ICOUNT -= 1 + 1 + 1;
else if (rs < 0x00010000) ARM7_ICOUNT -= 1 + 2 + 1;
@@ -1312,13 +1312,13 @@ static void HandleUMulLong(arm_state *cpustate, UINT32 insn)
static void HandleMemBlock(arm_state *cpustate, UINT32 insn)
{
- UINT32 rb = (insn & INSN_RN) >> INSN_RN_SHIFT;
- UINT32 rbp = GET_REGISTER(cpustate, rb);
- int result;
+ UINT32 rb = (insn & INSN_RN) >> INSN_RN_SHIFT;
+ UINT32 rbp = GET_REGISTER(cpustate, rb);
+ int result;
#if ARM7_DEBUG_CORE
- if (rbp & 3)
- LOG(("%08x: Unaligned Mem Transfer @ %08x\n", R15, rbp));
+ if (rbp & 3)
+ LOG(("%08x: Unaligned Mem Transfer @ %08x\n", R15, rbp));
#endif
// Normal LDM instructions take nS + 1N + 1I and LDM PC takes (n+1)S + 2N + 1I
@@ -1326,37 +1326,37 @@ static void HandleMemBlock(arm_state *cpustate, UINT32 insn)
// STM instructions take (n-1)S + 2N incremental cycles to execute, where n is the
// number of words transferred.
- if (insn & INSN_BDT_L)
- {
- /* Loading */
- if (insn & INSN_BDT_U)
- {
- /* Incrementing */
- if (!(insn & INSN_BDT_P))
- {
- rbp = rbp + (- 4);
- }
-
- // S Flag Set, but R15 not in list = User Bank Transfer
- if (insn & INSN_BDT_S && (insn & 0x8000) == 0)
- {
- // !! actually switching to user mode triggers a section permission fault in Happy Fish 302-in-1 (BP C0030DF4, press F5 ~16 times) !!
- // set to user mode - then do the transfer, and set back
- //int curmode = GET_MODE;
- //SwitchMode(cpustate, eARM7_MODE_USER);
- LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15));
- result = loadInc(cpustate, insn & 0xffff, rbp, insn & INSN_BDT_S, eARM7_MODE_USER);
- // todo - not sure if Writeback occurs on User registers also..
- //SwitchMode(cpustate, curmode);
- }
- else
- result = loadInc(cpustate, insn & 0xffff, rbp, insn & INSN_BDT_S, GET_MODE);
-
- if ((insn & INSN_BDT_W) && (cpustate->pendingAbtD == 0))
- {
+ if (insn & INSN_BDT_L)
+ {
+ /* Loading */
+ if (insn & INSN_BDT_U)
+ {
+ /* Incrementing */
+ if (!(insn & INSN_BDT_P))
+ {
+ rbp = rbp + (- 4);
+ }
+
+ // S Flag Set, but R15 not in list = User Bank Transfer
+ if (insn & INSN_BDT_S && (insn & 0x8000) == 0)
+ {
+ // !! actually switching to user mode triggers a section permission fault in Happy Fish 302-in-1 (BP C0030DF4, press F5 ~16 times) !!
+ // set to user mode - then do the transfer, and set back
+ //int curmode = GET_MODE;
+ //SwitchMode(cpustate, eARM7_MODE_USER);
+ LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15));
+ result = loadInc(cpustate, insn & 0xffff, rbp, insn & INSN_BDT_S, eARM7_MODE_USER);
+ // todo - not sure if Writeback occurs on User registers also..
+ //SwitchMode(cpustate, curmode);
+ }
+ else
+ result = loadInc(cpustate, insn & 0xffff, rbp, insn & INSN_BDT_S, GET_MODE);
+
+ if ((insn & INSN_BDT_W) && (cpustate->pendingAbtD == 0))
+ {
#if ARM7_DEBUG_CORE
- if (rb == 15)
- LOG(("%08x: Illegal LDRM writeback to r15\n", R15));
+ if (rb == 15)
+ LOG(("%08x: Illegal LDRM writeback to r15\n", R15));
#endif
// "A LDM will always overwrite the updated base if the base is in the list." (also for a user bank transfer?)
// GBA "V-Rally 3" expects R0 not to be overwritten with the updated base value [BP 8077B0C]
@@ -1364,168 +1364,168 @@ static void HandleMemBlock(arm_state *cpustate, UINT32 insn)
{
SET_REGISTER(cpustate, rb, GET_REGISTER(cpustate, rb) + result * 4);
}
- }
+ }
- // R15 included? (NOTE: CPSR restore must occur LAST otherwise wrong registers restored!)
- if ((insn & 0x8000) && (cpustate->pendingAbtD == 0)) {
- R15 -= 4; // SJE: I forget why i did this?
- // S - Flag Set? Signals transfer of current mode SPSR->CPSR
- if (insn & INSN_BDT_S)
+ // R15 included? (NOTE: CPSR restore must occur LAST otherwise wrong registers restored!)
+ if ((insn & 0x8000) && (cpustate->pendingAbtD == 0)) {
+ R15 -= 4; // SJE: I forget why i did this?
+ // S - Flag Set? Signals transfer of current mode SPSR->CPSR
+ if (insn & INSN_BDT_S)
{
- if (MODE32)
- {
- SET_CPSR(GET_REGISTER(cpustate, SPSR));
- SwitchMode(cpustate, GET_MODE);
- }
- else
- {
- UINT32 temp;
+ if (MODE32)
+ {
+ SET_CPSR(GET_REGISTER(cpustate, SPSR));
+ SwitchMode(cpustate, GET_MODE);
+ }
+ else
+ {
+ UINT32 temp;
// LOG(("LDM + S | R15 %08X CPSR %08X\n", R15, GET_CPSR));
temp = (GET_CPSR & 0x0FFFFF20) | (R15 & 0xF0000000) /* N Z C V */ | ((R15 & 0x0C000000) >> (26 - 6)) /* I F */ | (R15 & 0x00000003) /* M1 M0 */;
SET_CPSR( temp);
SwitchMode(cpustate, temp & 3);
- }
- }
- // LDM PC - takes 2 extra cycles
- ARM7_ICOUNT -= 2;
- }
- }
- else
- {
- /* Decrementing */
- if (!(insn & INSN_BDT_P))
- {
- rbp = rbp - (- 4);
- }
-
- // S Flag Set, but R15 not in list = User Bank Transfer
- if (insn & INSN_BDT_S && ((insn & 0x8000) == 0))
- {
- // set to user mode - then do the transfer, and set back
- //int curmode = GET_MODE;
- //SwitchMode(cpustate, eARM7_MODE_USER);
- LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15));
- result = loadDec(cpustate, insn & 0xffff, rbp, insn & INSN_BDT_S, eARM7_MODE_USER);
- // todo - not sure if Writeback occurs on User registers also..
- //SwitchMode(cpustate, curmode);
- }
- else
- result = loadDec(cpustate, insn & 0xffff, rbp, insn & INSN_BDT_S, GET_MODE);
-
- if ((insn & INSN_BDT_W) && (cpustate->pendingAbtD == 0))
- {
- if (rb == 0xf)
- LOG(("%08x: Illegal LDRM writeback to r15\n", R15));
+ }
+ }
+ // LDM PC - takes 2 extra cycles
+ ARM7_ICOUNT -= 2;
+ }
+ }
+ else
+ {
+ /* Decrementing */
+ if (!(insn & INSN_BDT_P))
+ {
+ rbp = rbp - (- 4);
+ }
+
+ // S Flag Set, but R15 not in list = User Bank Transfer
+ if (insn & INSN_BDT_S && ((insn & 0x8000) == 0))
+ {
+ // set to user mode - then do the transfer, and set back
+ //int curmode = GET_MODE;
+ //SwitchMode(cpustate, eARM7_MODE_USER);
+ LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15));
+ result = loadDec(cpustate, insn & 0xffff, rbp, insn & INSN_BDT_S, eARM7_MODE_USER);
+ // todo - not sure if Writeback occurs on User registers also..
+ //SwitchMode(cpustate, curmode);
+ }
+ else
+ result = loadDec(cpustate, insn & 0xffff, rbp, insn & INSN_BDT_S, GET_MODE);
+
+ if ((insn & INSN_BDT_W) && (cpustate->pendingAbtD == 0))
+ {
+ if (rb == 0xf)
+ LOG(("%08x: Illegal LDRM writeback to r15\n", R15));
// "A LDM will always overwrite the updated base if the base is in the list." (also for a user bank transfer?)
if (((insn >> rb) & 1) == 0)
{
SET_REGISTER(cpustate, rb, GET_REGISTER(cpustate, rb) - result * 4);
}
- }
+ }
- // R15 included? (NOTE: CPSR restore must occur LAST otherwise wrong registers restored!)
- if ((insn & 0x8000) && (cpustate->pendingAbtD == 0)) {
- R15 -= 4; // SJE: I forget why i did this?
- // S - Flag Set? Signals transfer of current mode SPSR->CPSR
- if (insn & INSN_BDT_S)
+ // R15 included? (NOTE: CPSR restore must occur LAST otherwise wrong registers restored!)
+ if ((insn & 0x8000) && (cpustate->pendingAbtD == 0)) {
+ R15 -= 4; // SJE: I forget why i did this?
+ // S - Flag Set? Signals transfer of current mode SPSR->CPSR
+ if (insn & INSN_BDT_S)
{
- if (MODE32)
- {
- SET_CPSR(GET_REGISTER(cpustate, SPSR));
- SwitchMode(cpustate, GET_MODE);
- }
- else
- {
- UINT32 temp;
+ if (MODE32)
+ {
+ SET_CPSR(GET_REGISTER(cpustate, SPSR));
+ SwitchMode(cpustate, GET_MODE);
+ }
+ else
+ {
+ UINT32 temp;
// LOG(("LDM + S | R15 %08X CPSR %08X\n", R15, GET_CPSR));
temp = (GET_CPSR & 0x0FFFFF20) /* N Z C V I F M4 M3 M2 M1 M0 */ | (R15 & 0xF0000000) /* N Z C V */ | ((R15 & 0x0C000000) >> (26 - 6)) /* I F */ | (R15 & 0x00000003) /* M1 M0 */;
SET_CPSR( temp);
SwitchMode(cpustate, temp & 3);
- }
- }
- // LDM PC - takes 2 extra cycles
- ARM7_ICOUNT -= 2;
- }
- }
- // LDM (NO PC) takes (n)S + 1N + 1I cycles (n = # of register transfers)
- ARM7_ICOUNT -= result + 1 + 1;
- } /* Loading */
- else
- {
- /* Storing */
- if (insn & (1 << eR15))
- {
+ }
+ }
+ // LDM PC - takes 2 extra cycles
+ ARM7_ICOUNT -= 2;
+ }
+ }
+ // LDM (NO PC) takes (n)S + 1N + 1I cycles (n = # of register transfers)
+ ARM7_ICOUNT -= result + 1 + 1;
+ } /* Loading */
+ else
+ {
+ /* Storing */
+ if (insn & (1 << eR15))
+ {
#if ARM7_DEBUG_CORE
- LOG(("%08x: Writing R15 in strm\n", R15));
+ LOG(("%08x: Writing R15 in strm\n", R15));
#endif
- /* special case handling if writing to PC */
- R15 += 12;
- }
- if (insn & INSN_BDT_U)
- {
- /* Incrementing */
- if (!(insn & INSN_BDT_P))
- {
- rbp = rbp + (- 4);
- }
-
- // S Flag Set = User Bank Transfer
- if (insn & INSN_BDT_S)
- {
- // todo: needs to be tested..
-
- // set to user mode - then do the transfer, and set back
- //int curmode = GET_MODE;
- //SwitchMode(cpustate, eARM7_MODE_USER);
- LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15));
- result = storeInc(cpustate, insn & 0xffff, rbp, eARM7_MODE_USER);
- // todo - not sure if Writeback occurs on User registers also..
- //SwitchMode(cpustate, curmode);
- }
- else
- result = storeInc(cpustate, insn & 0xffff, rbp, GET_MODE);
-
- if ((insn & INSN_BDT_W) && (cpustate->pendingAbtD == 0))
- {
- SET_REGISTER(cpustate, rb, GET_REGISTER(cpustate, rb) + result * 4);
- }
- }
- else
- {
- /* Decrementing */
- if (!(insn & INSN_BDT_P))
- {
- rbp = rbp - (-4);
- }
-
- // S Flag Set = User Bank Transfer
- if (insn & INSN_BDT_S)
- {
- // set to user mode - then do the transfer, and set back
- //int curmode = GET_MODE;
- //SwitchMode(cpustate, eARM7_MODE_USER);
- LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15));
- result = storeDec(cpustate, insn & 0xffff, rbp, eARM7_MODE_USER);
- // todo - not sure if Writeback occurs on User registers also..
- //SwitchMode(cpustate, curmode);
- }
- else
- result = storeDec(cpustate, insn & 0xffff, rbp, GET_MODE);
-
- if ((insn & INSN_BDT_W) && (cpustate->pendingAbtD == 0))
- {
- SET_REGISTER(cpustate, rb, GET_REGISTER(cpustate, rb) - result * 4);
- }
- }
- if (insn & (1 << eR15))
- R15 -= 12;
-
- // STM takes (n-1)S + 2N cycles (n = # of register transfers)
- ARM7_ICOUNT -= (result - 1) + 2;
- }
-
- // We will specify the cycle count for each case, so remove the -3 that occurs at the end
- ARM7_ICOUNT += 3;
+ /* special case handling if writing to PC */
+ R15 += 12;
+ }
+ if (insn & INSN_BDT_U)
+ {
+ /* Incrementing */
+ if (!(insn & INSN_BDT_P))
+ {
+ rbp = rbp + (- 4);
+ }
+
+ // S Flag Set = User Bank Transfer
+ if (insn & INSN_BDT_S)
+ {
+ // todo: needs to be tested..
+
+ // set to user mode - then do the transfer, and set back
+ //int curmode = GET_MODE;
+ //SwitchMode(cpustate, eARM7_MODE_USER);
+ LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15));
+ result = storeInc(cpustate, insn & 0xffff, rbp, eARM7_MODE_USER);
+ // todo - not sure if Writeback occurs on User registers also..
+ //SwitchMode(cpustate, curmode);
+ }
+ else
+ result = storeInc(cpustate, insn & 0xffff, rbp, GET_MODE);
+
+ if ((insn & INSN_BDT_W) && (cpustate->pendingAbtD == 0))
+ {
+ SET_REGISTER(cpustate, rb, GET_REGISTER(cpustate, rb) + result * 4);
+ }
+ }
+ else
+ {
+ /* Decrementing */
+ if (!(insn & INSN_BDT_P))
+ {
+ rbp = rbp - (-4);
+ }
+
+ // S Flag Set = User Bank Transfer
+ if (insn & INSN_BDT_S)
+ {
+ // set to user mode - then do the transfer, and set back
+ //int curmode = GET_MODE;
+ //SwitchMode(cpustate, eARM7_MODE_USER);
+ LOG(("%08x: User Bank Transfer not fully tested - please check if working properly!\n", R15));
+ result = storeDec(cpustate, insn & 0xffff, rbp, eARM7_MODE_USER);
+ // todo - not sure if Writeback occurs on User registers also..
+ //SwitchMode(cpustate, curmode);
+ }
+ else
+ result = storeDec(cpustate, insn & 0xffff, rbp, GET_MODE);
+
+ if ((insn & INSN_BDT_W) && (cpustate->pendingAbtD == 0))
+ {
+ SET_REGISTER(cpustate, rb, GET_REGISTER(cpustate, rb) - result * 4);
+ }
+ }
+ if (insn & (1 << eR15))
+ R15 -= 12;
+
+ // STM takes (n-1)S + 2N cycles (n = # of register transfers)
+ ARM7_ICOUNT -= (result - 1) + 2;
+ }
+
+ // We will specify the cycle count for each case, so remove the -3 that occurs at the end
+ ARM7_ICOUNT += 3;
} /* HandleMemBlock */
@@ -1551,7 +1551,7 @@ const void arm7ops_0123(arm_state *cpustate, UINT32 insn)
R15--;
}
}
- else if ((insn & 0x0ff000f0) == 0x01600010) // CLZ - v5
+ else if ((insn & 0x0ff000f0) == 0x01600010) // CLZ - v5
{
UINT32 rm = insn&0xf;
UINT32 rd = (insn>>12)&0xf;
@@ -1560,7 +1560,7 @@ const void arm7ops_0123(arm_state *cpustate, UINT32 insn)
R15 += 4;
}
- else if ((insn & 0x0ff000f0) == 0x01000050) // QADD - v5
+ else if ((insn & 0x0ff000f0) == 0x01000050) // QADD - v5
{
INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
INT32 src2 = GET_REGISTER(cpustate, (insn>>16)&0xf);
@@ -1571,7 +1571,7 @@ const void arm7ops_0123(arm_state *cpustate, UINT32 insn)
SET_REGISTER(cpustate, (insn>>12)&0xf, (INT32)res);
R15 += 4;
}
- else if ((insn & 0x0ff000f0) == 0x01400050) // QDADD - v5
+ else if ((insn & 0x0ff000f0) == 0x01400050) // QDADD - v5
{
INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
INT32 src2 = GET_REGISTER(cpustate, (insn>>16)&0xf);
@@ -1587,7 +1587,7 @@ const void arm7ops_0123(arm_state *cpustate, UINT32 insn)
SET_REGISTER(cpustate, (insn>>12)&0xf, (INT32)res);
R15 += 4;
}
- else if ((insn & 0x0ff000f0) == 0x01200050) // QSUB - v5
+ else if ((insn & 0x0ff000f0) == 0x01200050) // QSUB - v5
{
INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
INT32 src2 = GET_REGISTER(cpustate, (insn>>16)&0xf);
@@ -1598,7 +1598,7 @@ const void arm7ops_0123(arm_state *cpustate, UINT32 insn)
SET_REGISTER(cpustate, (insn>>12)&0xf, (INT32)res);
R15 += 4;
}
- else if ((insn & 0x0ff000f0) == 0x01600050) // QDSUB - v5
+ else if ((insn & 0x0ff000f0) == 0x01600050) // QDSUB - v5
{
INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
INT32 src2 = GET_REGISTER(cpustate, (insn>>16)&0xf);
@@ -1614,7 +1614,7 @@ const void arm7ops_0123(arm_state *cpustate, UINT32 insn)
SET_REGISTER(cpustate, (insn>>12)&0xf, (INT32)res);
R15 += 4;
}
- else if ((insn & 0x0ff00090) == 0x01000080) // SMLAxy - v5
+ else if ((insn & 0x0ff00090) == 0x01000080) // SMLAxy - v5
{
INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
INT32 src2 = GET_REGISTER(cpustate, (insn>>8)&0xf);
@@ -1655,7 +1655,7 @@ const void arm7ops_0123(arm_state *cpustate, UINT32 insn)
SET_REGISTER(cpustate, (insn>>16)&0xf, res1 + GET_REGISTER(cpustate, (insn>>12)&0xf));
R15 += 4;
}
- else if ((insn & 0x0ff00090) == 0x01400080) // SMLALxy - v5
+ else if ((insn & 0x0ff00090) == 0x01400080) // SMLALxy - v5
{
INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
INT32 src2 = GET_REGISTER(cpustate, (insn>>8)&0xf);
@@ -1698,7 +1698,7 @@ const void arm7ops_0123(arm_state *cpustate, UINT32 insn)
SET_REGISTER(cpustart, (insn>>12)&0xf, (UINT32)(dst&0xffffffff));
SET_REGISTER(cpustart, (insn>>16)&0xf, (UINT32)(dst>>32));
}
- else if ((insn & 0x0ff00090) == 0x01600080) // SMULxy - v5
+ else if ((insn & 0x0ff00090) == 0x01600080) // SMULxy - v5
{
INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
INT32 src2 = GET_REGISTER(cpustate, (insn>>8)&0xf);
@@ -1734,7 +1734,7 @@ const void arm7ops_0123(arm_state *cpustate, UINT32 insn)
res = src1 * src2;
SET_REGISTER(cpustart, (insn>>16)&0xf, res);
}
- else if ((insn & 0x0ff000b0) == 0x012000a0) // SMULWy - v5
+ else if ((insn & 0x0ff000b0) == 0x012000a0) // SMULWy - v5
{
INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
INT32 src2 = GET_REGISTER(cpustate, (insn>>8)&0xf);
@@ -1757,7 +1757,7 @@ const void arm7ops_0123(arm_state *cpustate, UINT32 insn)
res >>= 16;
SET_REGISTER(cpustart, (insn>>16)&0xf, (UINT32)res);
}
- else if ((insn & 0x0ff000b0) == 0x01200080) // SMLAWy - v5
+ else if ((insn & 0x0ff000b0) == 0x01200080) // SMLAWy - v5
{
INT32 src1 = GET_REGISTER(cpustate, insn&0xf);
INT32 src2 = GET_REGISTER(cpustate, (insn>>8)&0xf);