diff options
Diffstat (limited to 'src/devices/cpu/arm7/arm7ops.cpp')
-rw-r--r-- | src/devices/cpu/arm7/arm7ops.cpp | 156 |
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); |