diff options
Diffstat (limited to '')
-rw-r--r-- | src/citra_qt/debugger/callstack.cpp | 11 | ||||
-rw-r--r-- | src/citra_qt/debugger/callstack.h | 3 | ||||
-rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 331 | ||||
-rw-r--r-- | src/core/arm/interpreter/armsupp.cpp | 16 | ||||
-rw-r--r-- | src/core/arm/skyeye_common/armdefs.h | 1 |
5 files changed, 195 insertions, 167 deletions
diff --git a/src/citra_qt/debugger/callstack.cpp b/src/citra_qt/debugger/callstack.cpp index 025a5896b..9bb22ca2e 100644 --- a/src/citra_qt/debugger/callstack.cpp +++ b/src/citra_qt/debugger/callstack.cpp @@ -33,6 +33,8 @@ void CallstackWidget::OnDebugModeEntered() u32 sp = app_core->GetReg(13); //stack pointer u32 ret_addr, call_addr, func_addr; + Clear(); + int counter = 0; for (u32 addr = 0x10000000; addr >= sp; addr -= 4) { @@ -76,3 +78,12 @@ void CallstackWidget::OnDebugModeLeft() { } + +void CallstackWidget::Clear() +{ + for (int row = 0; row < callstack_model->rowCount(); row++) { + for (int column = 0; column < callstack_model->columnCount(); column++) { + callstack_model->setItem(row, column, new QStandardItem()); + } + } +} diff --git a/src/citra_qt/debugger/callstack.h b/src/citra_qt/debugger/callstack.h index fb390f5c3..1a9b6dc81 100644 --- a/src/citra_qt/debugger/callstack.h +++ b/src/citra_qt/debugger/callstack.h @@ -21,4 +21,7 @@ public slots: private: Ui::CallStack ui; QStandardItemModel* callstack_model; + + /// Clears the callstack widget while keeping the column widths the same + void Clear(); }; diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index bf864c7a7..b5e0993ed 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); @@ -3905,21 +3903,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 +3953,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,16 +3985,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)) { - u32 left = RN; - u32 right = SHIFTER_OPERAND; + if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { + adc_inst* const inst_cream = (adc_inst*)inst_base->component; - u64 unsigned_sum = (left + right + cpu->CFlag); - s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)cpu->CFlag; - u32 result = (unsigned_sum & 0xFFFFFFFF); + bool carry; + bool overflow; + RD = AddWithCarry(RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); - RD = result; if (inst_cream->S && (inst_cream->Rd == 15)) { if (CurrentModeHasSPSR) { cpu->Cpsr = cpu->Spsr_copy; @@ -4020,10 +3999,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { LOAD_NZCVT; } } else if (inst_cream->S) { - UPDATE_NFLAG(result); - UPDATE_ZFLAG(result); - UPDATE_CFLAG_CARRY_FROM_ADD(left, right, cpu->CFlag); - cpu->VFlag = ((s64)(s32)result != signed_sum); + UPDATE_NFLAG(RD); + UPDATE_ZFLAG(RD); + cpu->CFlag = carry; + cpu->VFlag = overflow; } if (inst_cream->Rd == 15) { INC_PC(sizeof(adc_inst)); @@ -4037,14 +4016,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; @@ -4052,10 +4034,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)); @@ -4071,9 +4053,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; @@ -4081,8 +4063,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) { @@ -4114,12 +4096,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; @@ -4127,8 +4109,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) { @@ -4234,15 +4216,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)); @@ -4251,19 +4235,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)); @@ -4321,12 +4307,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; @@ -4334,8 +4320,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) { @@ -4852,10 +4838,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)); @@ -4871,7 +4857,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; @@ -4879,8 +4865,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) { @@ -5016,10 +5002,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)); @@ -5033,9 +5019,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; @@ -5043,8 +5031,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) { @@ -5059,11 +5047,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; @@ -5071,8 +5061,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) { @@ -5292,14 +5282,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; @@ -5307,10 +5300,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)); @@ -5324,11 +5317,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; @@ -5336,10 +5331,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)); @@ -5462,11 +5457,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; @@ -5474,15 +5471,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)); @@ -6260,14 +6252,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; @@ -6275,10 +6270,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)); @@ -6406,18 +6401,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); @@ -6427,18 +6423,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); diff --git a/src/core/arm/interpreter/armsupp.cpp b/src/core/arm/interpreter/armsupp.cpp index 68ac2a0ce..e2626eefb 100644 --- a/src/core/arm/interpreter/armsupp.cpp +++ b/src/core/arm/interpreter/armsupp.cpp @@ -418,6 +418,22 @@ ARMul_NegZero (ARMul_State * state, ARMword result) } } +// Add with carry, indicates if a carry-out or signed overflow occurred. +u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred) +{ + u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in; + s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in; + u64 result = (unsigned_sum & 0xFFFFFFFF); + + if (carry_out_occurred) + *carry_out_occurred = (result != unsigned_sum); + + if (overflow_occurred) + *overflow_occurred = ((s64)(s32)result != signed_sum); + + return (u32)result; +} + // Compute whether an addition of A and B, giving RESULT, overflowed. bool AddOverflow(ARMword a, ARMword b, ARMword result) { diff --git a/src/core/arm/skyeye_common/armdefs.h b/src/core/arm/skyeye_common/armdefs.h index 1b2cef451..560b51a9f 100644 --- a/src/core/arm/skyeye_common/armdefs.h +++ b/src/core/arm/skyeye_common/armdefs.h @@ -795,6 +795,7 @@ extern void ARMul_FixSPSR(ARMul_State*, ARMword, ARMword); extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...); extern void ARMul_SelectProcessor(ARMul_State*, unsigned); +extern u32 AddWithCarry(u32, u32, u32, bool*, bool*); extern bool ARMul_AddOverflowQ(ARMword, ARMword); extern u8 ARMul_SignedSaturatedAdd8(u8, u8); |