summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/arm7/arm7ops.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/arm7/arm7ops.cpp')
-rw-r--r--src/devices/cpu/arm7/arm7ops.cpp156
1 files changed, 46 insertions, 110 deletions
diff --git a/src/devices/cpu/arm7/arm7ops.cpp b/src/devices/cpu/arm7/arm7ops.cpp
index f5a8f435762..416789a1e19 100644
--- a/src/devices/cpu/arm7/arm7ops.cpp
+++ b/src/devices/cpu/arm7/arm7ops.cpp
@@ -5,7 +5,7 @@
#include "arm7core.h"
#include "arm7help.h"
-#define LOG_OPS (1 << 0)
+#define LOG_OPS (1U << 1)
#define VERBOSE (0)
#include "logmacro.h"
@@ -102,7 +102,7 @@ uint32_t arm7_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry)
// 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;
+ return k ? (rm << k) : rm;
}
case 1: /* LSR */
@@ -122,7 +122,7 @@ uint32_t arm7_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry)
{
if (pCarry)
*pCarry = (rm & (1 << (k - 1)));
- return LSR(rm, k);
+ return rm >> k;
}
case 2: /* ASR */
@@ -136,9 +136,9 @@ uint32_t arm7_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry)
else
{
if (rm & SIGN_BIT)
- return LSR(rm, k) | (0xffffffffu << (32 - k));
+ return (rm >> k) | (0xffffffffu << (32 - k));
else
- return LSR(rm, k);
+ return rm >> k;
}
case 3: /* ROR and RRX */
@@ -149,7 +149,7 @@ uint32_t arm7_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry)
{
if (pCarry)
*pCarry = rm & (1 << (k - 1));
- return ROR(rm, k);
+ return rotr_32(rm, k);
}
else
{
@@ -163,7 +163,7 @@ uint32_t arm7_cpu_device::decodeShift(uint32_t insn, uint32_t *pCarry)
/* RRX */
if (pCarry)
*pCarry = (rm & 1);
- return LSR(rm, 1) | ((GET_CPSR & C_MASK) << 2);
+ return (rm >> 1) | ((GET_CPSR & C_MASK) << 2);
}
}
@@ -396,20 +396,10 @@ void arm7_cpu_device::HandleBranch(uint32_t insn, bool h_bit)
}
/* 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);
- }
+ if (MODE32)
+ R15 += util::sext(off, 26) + 8;
else
- {
- if (MODE32)
- R15 += off + 8;
- else
- R15 = ((R15 + (off + 8)) & 0x03FFFFFC) | (R15 & ~0x03FFFFFC);
- }
+ R15 = ((R15 + (util::sext(off, 26) + 8)) & 0x03FFFFFC) | (R15 & ~0x03FFFFFC);
}
void arm7_cpu_device::HandleMemSingle(uint32_t insn)
@@ -857,7 +847,7 @@ void arm7_cpu_device::HandlePSRTransfer(uint32_t insn)
// 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);
+ val = rotr_32(insn & INSN_OP2_IMM, by << 1);
else
val = insn & INSN_OP2_IMM;
}
@@ -967,7 +957,7 @@ void arm7_cpu_device::HandleALU(uint32_t insn)
by = (insn & INSN_OP2_ROTATE) >> INSN_OP2_ROTATE_SHIFT;
if (by)
{
- op2 = ROR(insn & INSN_OP2_IMM, by << 1);
+ op2 = rotr_32(insn & INSN_OP2_IMM, by << 1);
sc = op2 & SIGN_BIT;
}
else
@@ -1216,18 +1206,14 @@ void arm7_cpu_device::HandleMul(uint32_t insn)
// todo: add proper cycle counts
void arm7_cpu_device::HandleSMulLong(uint32_t insn)
{
- int32_t rm, rs;
- uint32_t rhi, rlo;
- int64_t res;
-
// 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_t)GetRegister(insn & 0xf);
- rs = (int32_t)GetRegister(((insn >> 8) & 0xf));
- rhi = (insn >> 16) & 0xf;
- rlo = (insn >> 12) & 0xf;
+ int32_t rm = (int32_t)GetRegister(insn & 0xf);
+ int32_t rs = (int32_t)GetRegister(((insn >> 8) & 0xf));
+ uint32_t rhi = (insn >> 16) & 0xf;
+ uint32_t rlo = (insn >> 12) & 0xf;
#if ARM7_DEBUG_CORE
if ((insn & 0xf) == 15 || ((insn >> 8) & 0xf) == 15 || ((insn >> 16) & 0xf) == 15 || ((insn >> 12) & 0xf) == 15)
@@ -1235,7 +1221,7 @@ void arm7_cpu_device::HandleSMulLong(uint32_t insn)
#endif
/* Perform the multiplication */
- res = (int64_t)rm * rs;
+ int64_t res = mul_32x32(rm, rs);
/* Add on Rn if this is a MLA */
if (insn & INSN_MUL_A)
@@ -1268,18 +1254,14 @@ void arm7_cpu_device::HandleSMulLong(uint32_t insn)
// todo: add proper cycle counts
void arm7_cpu_device::HandleUMulLong(uint32_t insn)
{
- uint32_t rm, rs;
- uint32_t rhi, rlo;
- uint64_t res;
-
// 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_t)GetRegister(insn & 0xf);
- rs = (int32_t)GetRegister(((insn >> 8) & 0xf));
- rhi = (insn >> 16) & 0xf;
- rlo = (insn >> 12) & 0xf;
+ uint32_t rm = GetRegister(insn & 0xf);
+ uint32_t rs = GetRegister(((insn >> 8) & 0xf));
+ uint32_t rhi = (insn >> 16) & 0xf;
+ uint32_t rlo = (insn >> 12) & 0xf;
#if ARM7_DEBUG_CORE
if (((insn & 0xf) == 15) || (((insn >> 8) & 0xf) == 15) || (((insn >> 16) & 0xf) == 15) || (((insn >> 12) & 0xf) == 15))
@@ -1287,7 +1269,7 @@ void arm7_cpu_device::HandleUMulLong(uint32_t insn)
#endif
/* Perform the multiplication */
- res = (uint64_t)rm * rs;
+ uint64_t res = mulu_32x32(rm, rs);
/* Add on Rn if this is a MLA */
if (insn & INSN_MUL_A)
@@ -1676,8 +1658,8 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn)
R15 = GetRegister(insn & 0x0f);
// If new PC address has A0 set, switch to Thumb mode
if (R15 & 1) {
- set_cpsr(GET_CPSR|T_MASK);
R15--;
+ set_cpsr(GET_CPSR|T_MASK);
}
}
else if ((insn & 0x0ff000f0) == 0x01200030) // BLX Rn - v5
@@ -1688,8 +1670,8 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn)
R15 = GetRegister(insn & 0x0f);
// If new PC address has A0 set, switch to Thumb mode
if (R15 & 1) {
- set_cpsr(GET_CPSR|T_MASK);
R15--;
+ set_cpsr(GET_CPSR|T_MASK);
}
}
else if ((insn & 0x0ff000f0) == 0x01600010) // CLZ - v5
@@ -1705,9 +1687,8 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn)
{
int32_t src1 = GetRegister(insn&0xf);
int32_t src2 = GetRegister((insn>>16)&0xf);
- int64_t res;
- res = saturate_qbit_overflow((int64_t)src1 + (int64_t)src2);
+ int64_t res = saturate_qbit_overflow((int64_t)src1 + (int64_t)src2);
SetRegister((insn>>12)&0xf, (int32_t)res);
R15 += 4;
@@ -1716,10 +1697,9 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn)
{
int32_t src1 = GetRegister(insn&0xf);
int32_t src2 = GetRegister((insn>>16)&0xf);
- int64_t res;
// check if doubling operation will overflow
- res = (int64_t)src2 * 2;
+ int64_t res = (int64_t)src2 * 2;
saturate_qbit_overflow(res);
src2 *= 2;
@@ -1732,9 +1712,8 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn)
{
int32_t src1 = GetRegister(insn&0xf);
int32_t src2 = GetRegister((insn>>16)&0xf);
- int64_t res;
- res = saturate_qbit_overflow((int64_t)src1 - (int64_t)src2);
+ int64_t res = saturate_qbit_overflow((int64_t)src1 - (int64_t)src2);
SetRegister((insn>>12)&0xf, (int32_t)res);
R15 += 4;
@@ -1743,10 +1722,9 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn)
{
int32_t src1 = GetRegister(insn&0xf);
int32_t src2 = GetRegister((insn>>16)&0xf);
- int64_t res;
// check if doubling operation will overflow
- res = (int64_t)src2 * 2;
+ int64_t res = (int64_t)src2 * 2;
saturate_qbit_overflow(res);
src2 *= 2;
@@ -1763,26 +1741,14 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn)
// select top and bottom halves of src1/src2 and sign extend if necessary
if (insn & 0x20)
- {
src1 >>= 16;
- }
-
- src1 &= 0xffff;
- if (src1 & 0x8000)
- {
- src1 |= 0xffff0000;
- }
+ else
+ src1 = util::sext(src1, 16);
if (insn & 0x40)
- {
src2 >>= 16;
- }
-
- src2 &= 0xffff;
- if (src2 & 0x8000)
- {
- src2 |= 0xffff0000;
- }
+ else
+ src2 = util::sext(src2, 16);
// do the signed multiply
res1 = src1 * src2;
@@ -1796,13 +1762,12 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn)
{
int32_t src1 = GetRegister(insn&0xf);
int32_t src2 = GetRegister((insn>>8)&0xf);
- int64_t dst;
- dst = (int64_t)GetRegister((insn>>12)&0xf);
+ int64_t dst = (int64_t)GetRegister((insn>>12)&0xf);
dst |= (int64_t)GetRegister((insn>>16)&0xf)<<32;
// do the multiply and accumulate
- dst += (int64_t)src1 * (int64_t)src2;
+ dst += mul_32x32(src1, src2);
// write back the result
SetRegister((insn>>12)&0xf, (uint32_t)dst);
@@ -1813,32 +1778,19 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn)
{
int32_t src1 = GetRegister(insn&0xf);
int32_t src2 = GetRegister((insn>>8)&0xf);
- int32_t res;
// select top and bottom halves of src1/src2 and sign extend if necessary
if (insn & 0x20)
- {
src1 >>= 16;
- }
-
- src1 &= 0xffff;
- if (src1 & 0x8000)
- {
- src1 |= 0xffff0000;
- }
+ else
+ src1 = util::sext(src1, 16);
if (insn & 0x40)
- {
src2 >>= 16;
- }
-
- src2 &= 0xffff;
- if (src2 & 0x8000)
- {
- src2 |= 0xffff0000;
- }
+ else
+ src2 = util::sext(src2, 16);
- res = src1 * src2;
+ int32_t res = src1 * src2;
SetRegister((insn>>16)&0xf, res);
R15 += 4;
}
@@ -1846,21 +1798,13 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn)
{
int32_t src1 = GetRegister(insn&0xf);
int32_t src2 = GetRegister((insn>>8)&0xf);
- int64_t res;
if (insn & 0x40)
- {
src2 >>= 16;
- }
-
- src2 &= 0xffff;
- if (src2 & 0x8000)
- {
- src2 |= 0xffff0000;
- }
+ else
+ src2 = util::sext(src2, 16);
- res = (int64_t)src1 * (int64_t)src2;
- res >>= 16;
+ int32_t res = mul_32x32_shift(src1, src2, 16);
SetRegister((insn>>16)&0xf, (uint32_t)res);
R15 += 4;
}
@@ -1869,27 +1813,19 @@ void arm7_cpu_device::arm7ops_0123(uint32_t insn)
int32_t src1 = GetRegister(insn&0xf);
int32_t src2 = GetRegister((insn>>8)&0xf);
int32_t src3 = GetRegister((insn>>12)&0xf);
- int64_t res;
if (insn & 0x40)
- {
src2 >>= 16;
- }
-
- src2 &= 0xffff;
- if (src2 & 0x8000)
- {
- src2 |= 0xffff0000;
- }
+ else
+ src2 = util::sext(src2, 16);
- res = (int64_t)src1 * (int64_t)src2;
- res >>= 16;
+ int32_t res = mul_32x32_shift(src1, src2, 16);
// check for overflow and set the Q bit
saturate_qbit_overflow((int64_t)src3 + res);
// do the real accumulate
- src3 += (int32_t)res;
+ src3 += res;
// write the result back
SetRegister((insn>>16)&0xf, (uint32_t)res);