diff options
Diffstat (limited to 'src/core/arm/dyncom')
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom.cpp | 11 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom.h | 7 | ||||
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 465 |
3 files changed, 248 insertions, 235 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp index c779e3fd4..9c4cc90f2 100644 --- a/src/core/arm/dyncom/arm_dyncom.cpp +++ b/src/core/arm/dyncom/arm_dyncom.cpp @@ -9,13 +9,14 @@ #include "core/arm/dyncom/arm_dyncom.h" #include "core/arm/dyncom/arm_dyncom_interpreter.h" +#include "core/core.h" #include "core/core_timing.h" const static cpu_config_t s_arm11_cpu_info = { "armv6", "arm11", 0x0007b000, 0x0007f000, NONCACHE }; -ARM_DynCom::ARM_DynCom() : ticks(0) { +ARM_DynCom::ARM_DynCom() { state = std::unique_ptr<ARMul_State>(new ARMul_State); ARMul_EmulateInit(); @@ -74,11 +75,11 @@ void ARM_DynCom::SetCPSR(u32 cpsr) { } u64 ARM_DynCom::GetTicks() const { - return ticks; + // TODO(Subv): Remove ARM_DynCom::GetTicks() and use CoreTiming::GetTicks() directly once ARMemu is gone + return CoreTiming::GetTicks(); } void ARM_DynCom::AddTicks(u64 ticks) { - this->ticks += ticks; down_count -= ticks; if (down_count < 0) CoreTiming::Advance(); @@ -94,7 +95,7 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) { AddTicks(ticks_executed); } -void ARM_DynCom::SaveContext(ThreadContext& ctx) { +void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) { memcpy(ctx.cpu_registers, state->Reg, sizeof(ctx.cpu_registers)); memcpy(ctx.fpu_registers, state->ExtReg, sizeof(ctx.fpu_registers)); @@ -110,7 +111,7 @@ void ARM_DynCom::SaveContext(ThreadContext& ctx) { ctx.mode = state->NextInstr; } -void ARM_DynCom::LoadContext(const ThreadContext& ctx) { +void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) { memcpy(state->Reg, ctx.cpu_registers, sizeof(ctx.cpu_registers)); memcpy(state->ExtReg, ctx.fpu_registers, sizeof(ctx.fpu_registers)); diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h index 7284dcd07..f16fb070c 100644 --- a/src/core/arm/dyncom/arm_dyncom.h +++ b/src/core/arm/dyncom/arm_dyncom.h @@ -71,13 +71,13 @@ public: * Saves the current CPU context * @param ctx Thread context to save */ - void SaveContext(ThreadContext& ctx) override; + void SaveContext(Core::ThreadContext& ctx) override; /** * Loads a CPU context * @param ctx Thread context to load */ - void LoadContext(const ThreadContext& ctx) override; + void LoadContext(const Core::ThreadContext& ctx) override; /// Prepare core for thread reschedule (if needed to correctly handle state) void PrepareReschedule() override; @@ -89,8 +89,5 @@ public: void ExecuteInstructions(int num_instructions) override; private: - std::unique_ptr<ARMul_State> state; - u64 ticks; - }; diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 7c710ccde..d0347566c 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp @@ -176,13 +176,11 @@ unsigned int DPO(ArithmeticShiftRightByImmediate)(arm_processor *cpu, unsigned i unsigned int shifter_operand; int shift_imm = BITS(sht_oper, 7, 11); if (shift_imm == 0) { - if (BIT(rm, 31)) { + if (BIT(rm, 31) == 0) shifter_operand = 0; - cpu->shifter_carry_out = BIT(rm, 31); - } else { + else shifter_operand = 0xFFFFFFFF; - cpu->shifter_carry_out = BIT(rm, 31); - } + cpu->shifter_carry_out = BIT(rm, 31); } else { shifter_operand = static_cast<int>(rm) >> shift_imm; cpu->shifter_carry_out = BIT(rm, shift_imm - 1); @@ -1728,25 +1726,21 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(ldrb)(unsigned int inst, int index) } ARM_INST_PTR INTERPRETER_TRANSLATE(ldrbt)(unsigned int inst, int index) { - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst* inst_cream = (ldst_inst*)inst_base->component; inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->idx = index; + inst_base->br = NON_BRANCH; inst_cream->inst = inst; - if (I_BIT == 0) { + if (BITS(inst, 25, 27) == 2) { inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); + } else if (BITS(inst, 25, 27) == 3) { + inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed); } else { DEBUG_MSG; } - #if 0 - inst_cream->get_addr = get_calc_addr_op(inst); - if(inst == 0x54f13001) { - DEBUG_LOG(ARM11, "get_calc_addr_op:%llx\n", inst_cream->get_addr); - } - #endif if (BITS(inst, 12, 15) == 15) { inst_base->br = INDIRECT_BRANCH; @@ -1846,17 +1840,24 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(ldrsh)(unsigned int inst, int index) } ARM_INST_PTR INTERPRETER_TRANSLATE(ldrt)(unsigned int inst, int index) { - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst* inst_cream = (ldst_inst*)inst_base->component; inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->idx = index; + inst_base->br = NON_BRANCH; inst_cream->inst = inst; - if (I_BIT == 0) { + if (BITS(inst, 25, 27) == 2) { inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); + } else if (BITS(inst, 25, 27) == 3) { + inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed); } else { + // Reaching this would indicate the thumb version + // of this instruction, however the 3DS CPU doesn't + // support this variant (the 3DS CPU is only ARMv6K, + // while this variant is added in ARMv6T2). + // So it's sufficient for citra to not implement this. DEBUG_MSG; } @@ -2714,17 +2715,19 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(strb)(unsigned int inst, int index) } ARM_INST_PTR INTERPRETER_TRANSLATE(strbt)(unsigned int inst, int index) { - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst* inst_cream = (ldst_inst*)inst_base->component; inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->idx = index; + inst_base->br = NON_BRANCH; inst_cream->inst = inst; -// inst_cream->get_addr = get_calc_addr_op(inst); - if (I_BIT == 0) { + + if (BITS(inst, 25, 27) == 2) { inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); + } else if (BITS(inst, 25, 27) == 3) { + inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed); } else { DEBUG_MSG; } @@ -2796,17 +2799,24 @@ ARM_INST_PTR INTERPRETER_TRANSLATE(strh)(unsigned int inst, int index) } ARM_INST_PTR INTERPRETER_TRANSLATE(strt)(unsigned int inst, int index) { - arm_inst *inst_base = (arm_inst *)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); - ldst_inst *inst_cream = (ldst_inst *)inst_base->component; + arm_inst* inst_base = (arm_inst*)AllocBuffer(sizeof(arm_inst) + sizeof(ldst_inst)); + ldst_inst* inst_cream = (ldst_inst*)inst_base->component; inst_base->cond = BITS(inst, 28, 31); - inst_base->idx = index; - inst_base->br = NON_BRANCH; + inst_base->idx = index; + inst_base->br = NON_BRANCH; inst_cream->inst = inst; - if (I_BIT == 0) { + if (BITS(inst, 25, 27) == 2) { inst_cream->get_addr = LnSWoUB(ImmediatePostIndexed); + } else if (BITS(inst, 25, 27) == 3) { + inst_cream->get_addr = LnSWoUB(ScaledRegisterPostIndexed); } else { + // Reaching this would indicate the thumb version + // of this instruction, however the 3DS CPU doesn't + // support this variant (the 3DS CPU is only ARMv6K, + // while this variant is added in ARMv6T2). + // So it's sufficient for citra to not implement this. DEBUG_MSG; } @@ -3905,21 +3915,9 @@ unsigned InterpreterMainLoop(ARMul_State* state) { } #endif - #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0) - #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1) - - #define UPDATE_CFLAG(dst, lop, rop) (cpu->CFlag = ((dst < lop) || (dst < rop))) - #define UPDATE_CFLAG_CARRY_FROM_ADD(lop, rop, flag) (cpu->CFlag = (((uint64_t) lop + (uint64_t) rop + (uint64_t) flag) > 0xffffffff) ) - #define UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(lop, rop, flag) (cpu->CFlag = ((uint64_t) lop >= ((uint64_t) rop + (uint64_t) flag))) - #define UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop) (cpu->CFlag = (lop >= rop)) - #define UPDATE_CFLAG_WITH_NOT(dst, lop, rop) (cpu->CFlag = !(dst < lop)) - #define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out) - - #define UPDATE_VFLAG(dst, lop, rop) (cpu->VFlag = (((lop < 0) && (rop < 0) && (dst >= 0)) || \ - ((lop >= 0) && (rop) >= 0 && (dst < 0)))) - #define UPDATE_VFLAG_WITH_NOT(dst, lop, rop) (cpu->VFlag = !(((lop < 0) && (rop < 0) && (dst >= 0)) || \ - ((lop >= 0) && (rop) >= 0 && (dst < 0)))) - #define UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop) (cpu->VFlag = (((lop ^ rop) & (lop ^ dst)) >> 31)) + #define UPDATE_NFLAG(dst) (cpu->NFlag = BIT(dst, 31) ? 1 : 0) + #define UPDATE_ZFLAG(dst) (cpu->ZFlag = dst ? 0 : 1) + #define UPDATE_CFLAG_WITH_SC (cpu->CFlag = cpu->shifter_carry_out) #define SAVE_NZCVT cpu->Cpsr = (cpu->Cpsr & 0x0fffffdf) | \ (cpu->NFlag << 31) | \ @@ -3967,16 +3965,12 @@ unsigned InterpreterMainLoop(ARMul_State* state) { &&INIT_INST_LENGTH,&&END }; #endif - arm_inst * inst_base; - unsigned int lop, rop, dst; + arm_inst* inst_base; unsigned int addr; unsigned int phys_addr; - unsigned int last_pc = 0; unsigned int num_instrs = 0; - static unsigned int last_physical_base = 0, last_logical_base = 0; int ptr; - bool single_step = (cpu->NumInstrsToExecute == 1); LOAD_NZCVT; DISPATCH: @@ -4003,12 +3997,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) { } ADC_INST: { - adc_inst *inst_cream = (adc_inst *)inst_base->component; - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - lop = RN; - unsigned int sht_op = SHIFTER_OPERAND; - rop = SHIFTER_OPERAND + cpu->CFlag; - RD = dst = lop + rop; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + adc_inst* const inst_cream = (adc_inst*)inst_base->component; + + bool carry; + bool overflow; + RD = AddWithCarry(RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); + if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; @@ -4016,10 +4011,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOAD_NZCVT; } } else if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); - UPDATE_CFLAG_CARRY_FROM_ADD(lop, sht_op, cpu->CFlag); - UPDATE_VFLAG((int)dst, (int)lop, (int)rop); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); + cpu->CFlag = carry; + cpu->VFlag = overflow; } if (inst_cream->Rd == 15) { INC_PC(sizeof(adc_inst)); @@ -4033,14 +4028,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) { } ADD_INST: { - add_inst *inst_cream = (add_inst *)inst_base->component; - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - lop = RN; - if (inst_cream->Rn == 15) { - lop += 2 * GET_INST_SIZE(cpu); - } - rop = SHIFTER_OPERAND; - RD = dst = lop + rop; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + add_inst* const inst_cream = (add_inst*)inst_base->component; + + u32 rn_val = RN; + if (inst_cream->Rn == 15) + rn_val += 2 * GET_INST_SIZE(cpu); + + bool carry; + bool overflow; + RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow); + if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; @@ -4048,10 +4046,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOAD_NZCVT; } } else if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); - UPDATE_CFLAG(dst, lop, rop); - UPDATE_VFLAG((int)dst, (int)lop, (int)rop); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); + cpu->CFlag = carry; + cpu->VFlag = overflow; } if (inst_cream->Rd == 15) { INC_PC(sizeof(add_inst)); @@ -4067,9 +4065,9 @@ unsigned InterpreterMainLoop(ARMul_State* state) { { and_inst *inst_cream = (and_inst *)inst_base->component; if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - lop = RN; - rop = SHIFTER_OPERAND; - RD = dst = lop & rop; + u32 lop = RN; + u32 rop = SHIFTER_OPERAND; + RD = lop & rop; if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; @@ -4077,8 +4075,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOAD_NZCVT; } } else if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); UPDATE_CFLAG_WITH_SC; } if (inst_cream->Rd == 15) { @@ -4110,12 +4108,12 @@ unsigned InterpreterMainLoop(ARMul_State* state) { { bic_inst *inst_cream = (bic_inst *)inst_base->component; if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - lop = RN; + u32 lop = RN; if (inst_cream->Rn == 15) { lop += 2 * GET_INST_SIZE(cpu); } - rop = SHIFTER_OPERAND; - RD = dst = lop & (~rop); + u32 rop = SHIFTER_OPERAND; + RD = lop & (~rop); if ((inst_cream->S) && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; @@ -4123,8 +4121,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOAD_NZCVT; } } else if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); UPDATE_CFLAG_WITH_SC; } if (inst_cream->Rd == 15) { @@ -4230,15 +4228,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) { } CMN_INST: { - cmn_inst *inst_cream = (cmn_inst *)inst_base->component; - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - lop = RN; - rop = SHIFTER_OPERAND; - dst = lop + rop; - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); - UPDATE_CFLAG(dst, lop, rop); - UPDATE_VFLAG((int)dst, (int)lop, (int)rop); + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + cmn_inst* const inst_cream = (cmn_inst*)inst_base->component; + + bool carry; + bool overflow; + u32 result = AddWithCarry(RN, SHIFTER_OPERAND, 0, &carry, &overflow); + + UPDATE_NFLAG(result); + UPDATE_ZFLAG(result); + cpu->CFlag = carry; + cpu->VFlag = overflow; } cpu->Reg[15] += GET_INST_SIZE(cpu); INC_PC(sizeof(cmn_inst)); @@ -4247,19 +4247,21 @@ unsigned InterpreterMainLoop(ARMul_State* state) { } CMP_INST: { - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - cmp_inst *inst_cream = (cmp_inst *)inst_base->component; - lop = RN; - if (inst_cream->Rn == 15) { - lop += 2 * GET_INST_SIZE(cpu); - } - rop = SHIFTER_OPERAND; - dst = lop - rop; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + cmp_inst* const inst_cream = (cmp_inst*)inst_base->component; - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); - UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop); - UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop); + u32 rn_val = RN; + if (inst_cream->Rn == 15) + rn_val += 2 * GET_INST_SIZE(cpu); + + bool carry; + bool overflow; + u32 result = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow); + + UPDATE_NFLAG(result); + UPDATE_ZFLAG(result); + cpu->CFlag = carry; + cpu->VFlag = overflow; } cpu->Reg[15] += GET_INST_SIZE(cpu); INC_PC(sizeof(cmp_inst)); @@ -4317,12 +4319,12 @@ unsigned InterpreterMainLoop(ARMul_State* state) { { eor_inst *inst_cream = (eor_inst *)inst_base->component; if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - lop = RN; + u32 lop = RN; if (inst_cream->Rn == 15) { lop += 2 * GET_INST_SIZE(cpu); } - rop = SHIFTER_OPERAND; - RD = dst = lop ^ rop; + u32 rop = SHIFTER_OPERAND; + RD = lop ^ rop; if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; @@ -4330,8 +4332,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOAD_NZCVT; } } else if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); UPDATE_CFLAG_WITH_SC; } if (inst_cream->Rd == 15) { @@ -4848,10 +4850,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOG_ERROR(Core_ARM11, "invalid operands for MLA"); CITRA_IGNORE_EXIT(-1); } - RD = dst = static_cast<uint32_t>((rm * rs + rn) & 0xffffffff); + RD = static_cast<uint32_t>((rm * rs + rn) & 0xffffffff); if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); } if (inst_cream->Rd == 15) { INC_PC(sizeof(mla_inst)); @@ -4867,7 +4869,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) { { mov_inst *inst_cream = (mov_inst *)inst_base->component; if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - RD = dst = SHIFTER_OPERAND; + RD = SHIFTER_OPERAND; if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; @@ -4875,8 +4877,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOAD_NZCVT; } } else if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); UPDATE_CFLAG_WITH_SC; } if (inst_cream->Rd == 15) { @@ -4964,39 +4966,41 @@ unsigned InterpreterMainLoop(ARMul_State* state) { } MSR_INST: { - msr_inst *inst_cream = (msr_inst *)inst_base->component; - const uint32_t UnallocMask = 0x06f0fc00, UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; - unsigned int inst = inst_cream->inst; - unsigned int operand; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + msr_inst *inst_cream = (msr_inst *)inst_base->component; + const uint32_t UnallocMask = 0x06f0fc00, UserMask = 0xf80f0200, PrivMask = 0x000001df, StateMask = 0x01000020; + unsigned int inst = inst_cream->inst; + unsigned int operand; - if (BIT(inst, 25)) { - int rot_imm = BITS(inst, 8, 11) * 2; - operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm); - } else { - operand = cpu->Reg[BITS(inst, 0, 3)]; - } - uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) - | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); - uint32_t mask; - if (!inst_cream->R) { - if (InAPrivilegedMode(cpu)) { - if ((operand & StateMask) != 0) { - /// UNPREDICTABLE - DEBUG_MSG; - } else - mask = byte_mask & (UserMask | PrivMask); + if (BIT(inst, 25)) { + int rot_imm = BITS(inst, 8, 11) * 2; + operand = ROTATE_RIGHT_32(BITS(inst, 0, 7), rot_imm); } else { - mask = byte_mask & UserMask; + operand = cpu->Reg[BITS(inst, 0, 3)]; } - SAVE_NZCVT; + uint32_t byte_mask = (BIT(inst, 16) ? 0xff : 0) | (BIT(inst, 17) ? 0xff00 : 0) + | (BIT(inst, 18) ? 0xff0000 : 0) | (BIT(inst, 19) ? 0xff000000 : 0); + uint32_t mask; + if (!inst_cream->R) { + if (InAPrivilegedMode(cpu)) { + if ((operand & StateMask) != 0) { + /// UNPREDICTABLE + DEBUG_MSG; + } else + mask = byte_mask & (UserMask | PrivMask); + } else { + mask = byte_mask & UserMask; + } + SAVE_NZCVT; - cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); - switch_mode(cpu, cpu->Cpsr & 0x1f); - LOAD_NZCVT; - } else { - if (CurrentModeHasSPSR) { - mask = byte_mask & (UserMask | PrivMask | StateMask); - cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask); + cpu->Cpsr = (cpu->Cpsr & ~mask) | (operand & mask); + switch_mode(cpu, cpu->Cpsr & 0x1f); + LOAD_NZCVT; + } else { + if (CurrentModeHasSPSR) { + mask = byte_mask & (UserMask | PrivMask | StateMask); + cpu->Spsr_copy = (cpu->Spsr_copy & ~mask) | (operand & mask); + } } } cpu->Reg[15] += GET_INST_SIZE(cpu); @@ -5010,10 +5014,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { uint64_t rm = RM; uint64_t rs = RS; - RD = dst = static_cast<uint32_t>((rm * rs) & 0xffffffff); + RD = static_cast<uint32_t>((rm * rs) & 0xffffffff); if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); } if (inst_cream->Rd == 15) { INC_PC(sizeof(mul_inst)); @@ -5027,9 +5031,11 @@ unsigned InterpreterMainLoop(ARMul_State* state) { } MVN_INST: { - mvn_inst *inst_cream = (mvn_inst *)inst_base->component; - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - RD = dst = ~SHIFTER_OPERAND; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + mvn_inst* const inst_cream = (mvn_inst*)inst_base->component; + + RD = ~SHIFTER_OPERAND; + if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; @@ -5037,8 +5043,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOAD_NZCVT; } } else if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); UPDATE_CFLAG_WITH_SC; } if (inst_cream->Rd == 15) { @@ -5053,11 +5059,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) { } ORR_INST: { - orr_inst *inst_cream = (orr_inst *)inst_base->component; - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - lop = RN; - rop = SHIFTER_OPERAND; - RD = dst = lop | rop; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + orr_inst* const inst_cream = (orr_inst*)inst_base->component; + + u32 lop = RN; + u32 rop = SHIFTER_OPERAND; + RD = lop | rop; + if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; @@ -5065,8 +5073,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOAD_NZCVT; } } else if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); UPDATE_CFLAG_WITH_SC; } if (inst_cream->Rd == 15) { @@ -5286,14 +5294,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) { RFE_INST: RSB_INST: { - rsb_inst *inst_cream = (rsb_inst *)inst_base->component; - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - rop = RN; - lop = SHIFTER_OPERAND; - if (inst_cream->Rn == 15) { - rop += 2 * GET_INST_SIZE(cpu);; - } - RD = dst = lop - rop; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + rsb_inst* const inst_cream = (rsb_inst*)inst_base->component; + + u32 rn_val = RN; + if (inst_cream->Rn == 15) + rn_val += 2 * GET_INST_SIZE(cpu); + + bool carry; + bool overflow; + RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow); + if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; @@ -5301,10 +5312,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOAD_NZCVT; } } else if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); - UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop); - UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); + cpu->CFlag = carry; + cpu->VFlag = overflow; } if (inst_cream->Rd == 15) { INC_PC(sizeof(rsb_inst)); @@ -5318,11 +5329,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) { } RSC_INST: { - rsc_inst *inst_cream = (rsc_inst *)inst_base->component; - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - lop = RN; - rop = SHIFTER_OPERAND; - RD = dst = rop - lop - !cpu->CFlag; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + rsc_inst* const inst_cream = (rsc_inst*)inst_base->component; + + bool carry; + bool overflow; + RD = AddWithCarry(~RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); + if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; @@ -5330,10 +5343,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOAD_NZCVT; } } else if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); - UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(rop, lop, !cpu->CFlag); - UPDATE_VFLAG_OVERFLOW_FROM((int)dst, (int)rop, (int)lop); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); + cpu->CFlag = carry; + cpu->VFlag = overflow; } if (inst_cream->Rd == 15) { INC_PC(sizeof(rsc_inst)); @@ -5456,11 +5469,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) { SBC_INST: { - sbc_inst *inst_cream = (sbc_inst *)inst_base->component; - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - lop = SHIFTER_OPERAND + !cpu->CFlag; - rop = RN; - RD = dst = rop - lop; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + sbc_inst* const inst_cream = (sbc_inst*)inst_base->component; + + bool carry; + bool overflow; + RD = AddWithCarry(RN, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); + if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; @@ -5468,15 +5483,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOAD_NZCVT; } } else if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); - - if(rop >= !cpu->CFlag) - UPDATE_CFLAG_NOT_BORROW_FROM(rop - !cpu->CFlag, SHIFTER_OPERAND); - else - UPDATE_CFLAG_NOT_BORROW_FROM(rop, !cpu->CFlag); - - UPDATE_VFLAG_OVERFLOW_FROM(dst, rop, lop); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); + cpu->CFlag = carry; + cpu->VFlag = overflow; } if (inst_cream->Rd == 15) { INC_PC(sizeof(sbc_inst)); @@ -6254,14 +6264,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) { } SUB_INST: { - sub_inst *inst_cream = (sub_inst *)inst_base->component; - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - lop = RN; - if (inst_cream->Rn == 15) { - lop += 8; - } - rop = SHIFTER_OPERAND; - RD = dst = lop - rop; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + sub_inst* const inst_cream = (sub_inst*)inst_base->component; + + u32 rn_val = RN; + if (inst_cream->Rn == 15) + rn_val += 8; + + bool carry; + bool overflow; + RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow); + if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; @@ -6269,10 +6282,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOAD_NZCVT; } } else if (inst_cream->S) { - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); - UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop); - UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); + cpu->CFlag = carry; + cpu->VFlag = overflow; } if (inst_cream->Rd == 15) { INC_PC(sizeof(sub_inst)); @@ -6400,18 +6413,19 @@ unsigned InterpreterMainLoop(ARMul_State* state) { TEQ_INST: { - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - teq_inst *inst_cream = (teq_inst *)inst_base->component; - lop = RN; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + teq_inst* const inst_cream = (teq_inst*)inst_base->component; + + u32 lop = RN; + u32 rop = SHIFTER_OPERAND; if (inst_cream->Rn == 15) lop += GET_INST_SIZE(cpu) * 2; - rop = SHIFTER_OPERAND; - dst = lop ^ rop; + u32 result = lop ^ rop; - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); + UPDATE_NFLAG(result); + UPDATE_ZFLAG(result); UPDATE_CFLAG_WITH_SC; } cpu->Reg[15] += GET_INST_SIZE(cpu); @@ -6421,18 +6435,19 @@ unsigned InterpreterMainLoop(ARMul_State* state) { } TST_INST: { - if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { - tst_inst *inst_cream = (tst_inst *)inst_base->component; - lop = RN; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + tst_inst* const inst_cream = (tst_inst*)inst_base->component; + + u32 lop = RN; + u32 rop = SHIFTER_OPERAND; if (inst_cream->Rn == 15) lop += GET_INST_SIZE(cpu) * 2; - rop = SHIFTER_OPERAND; - dst = lop & rop; + u32 result = lop & rop; - UPDATE_NFLAG(dst); - UPDATE_ZFLAG(dst); + UPDATE_NFLAG(result); + UPDATE_ZFLAG(result); UPDATE_CFLAG_WITH_SC; } cpu->Reg[15] += GET_INST_SIZE(cpu); @@ -6696,10 +6711,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { { if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { umaal_inst* const inst_cream = (umaal_inst*)inst_base->component; - const u32 rm = RM; - const u32 rn = RN; - const u32 rd_lo = RDLO; - const u32 rd_hi = RDHI; + const u64 rm = RM; + const u64 rn = RN; + const u64 rd_lo = RDLO; + const u64 rd_hi = RDHI; const u64 result = (rm * rn) + rd_lo + rd_hi; RDLO = (result & 0xFFFFFFFF); |
