diff options
| author | 2015-01-12 00:43:12 -0500 | |
|---|---|---|
| committer | 2015-01-12 01:03:58 -0500 | |
| commit | 3ace75a49f54d73a1d3ba876ef8dc0b03adc677f (patch) | |
| tree | 19d25fb8240bdb0759e3e61364a26aa37e2af03b /src/core | |
| parent | dyncom: Add a helper function for addition with a carry (diff) | |
| download | yuzu-3ace75a49f54d73a1d3ba876ef8dc0b03adc677f.tar.gz yuzu-3ace75a49f54d73a1d3ba876ef8dc0b03adc677f.tar.xz yuzu-3ace75a49f54d73a1d3ba876ef8dc0b03adc677f.zip | |
dyncom: Fix overflow flag setting for ADD/RSB/RSC/SUB/SBC
Also cleans up CMN, and CMP.
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 79 |
1 files changed, 41 insertions, 38 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index 4c0a8f5cb..88982d5fb 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -4034,14 +4034,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 4034 | } | 4034 | } |
| 4035 | ADD_INST: | 4035 | ADD_INST: |
| 4036 | { | 4036 | { |
| 4037 | add_inst *inst_cream = (add_inst *)inst_base->component; | 4037 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 4038 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 4038 | add_inst* const inst_cream = (add_inst*)inst_base->component; |
| 4039 | lop = RN; | 4039 | |
| 4040 | if (inst_cream->Rn == 15) { | 4040 | u32 rn_val = RN; |
| 4041 | lop += 2 * GET_INST_SIZE(cpu); | 4041 | if (inst_cream->Rn == 15) |
| 4042 | } | 4042 | rn_val += 2 * GET_INST_SIZE(cpu); |
| 4043 | rop = SHIFTER_OPERAND; | 4043 | |
| 4044 | RD = dst = lop + rop; | 4044 | bool carry; |
| 4045 | bool overflow; | ||
| 4046 | RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow); | ||
| 4047 | |||
| 4045 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 4048 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 4046 | if (CurrentModeHasSPSR) { | 4049 | if (CurrentModeHasSPSR) { |
| 4047 | cpu->Cpsr = cpu->Spsr_copy; | 4050 | cpu->Cpsr = cpu->Spsr_copy; |
| @@ -4049,10 +4052,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 4049 | LOAD_NZCVT; | 4052 | LOAD_NZCVT; |
| 4050 | } | 4053 | } |
| 4051 | } else if (inst_cream->S) { | 4054 | } else if (inst_cream->S) { |
| 4052 | UPDATE_NFLAG(dst); | 4055 | UPDATE_NFLAG(RD); |
| 4053 | UPDATE_ZFLAG(dst); | 4056 | UPDATE_ZFLAG(RD); |
| 4054 | UPDATE_CFLAG(dst, lop, rop); | 4057 | cpu->CFlag = carry; |
| 4055 | UPDATE_VFLAG((int)dst, (int)lop, (int)rop); | 4058 | cpu->VFlag = overflow; |
| 4056 | } | 4059 | } |
| 4057 | if (inst_cream->Rd == 15) { | 4060 | if (inst_cream->Rd == 15) { |
| 4058 | INC_PC(sizeof(add_inst)); | 4061 | INC_PC(sizeof(add_inst)); |
| @@ -5459,11 +5462,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 5459 | 5462 | ||
| 5460 | SBC_INST: | 5463 | SBC_INST: |
| 5461 | { | 5464 | { |
| 5462 | sbc_inst *inst_cream = (sbc_inst *)inst_base->component; | 5465 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 5463 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 5466 | sbc_inst* const inst_cream = (sbc_inst*)inst_base->component; |
| 5464 | lop = SHIFTER_OPERAND + !cpu->CFlag; | 5467 | |
| 5465 | rop = RN; | 5468 | bool carry; |
| 5466 | RD = dst = rop - lop; | 5469 | bool overflow; |
| 5470 | RD = AddWithCarry(RN, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); | ||
| 5471 | |||
| 5467 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 5472 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 5468 | if (CurrentModeHasSPSR) { | 5473 | if (CurrentModeHasSPSR) { |
| 5469 | cpu->Cpsr = cpu->Spsr_copy; | 5474 | cpu->Cpsr = cpu->Spsr_copy; |
| @@ -5471,15 +5476,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 5471 | LOAD_NZCVT; | 5476 | LOAD_NZCVT; |
| 5472 | } | 5477 | } |
| 5473 | } else if (inst_cream->S) { | 5478 | } else if (inst_cream->S) { |
| 5474 | UPDATE_NFLAG(dst); | 5479 | UPDATE_NFLAG(RD); |
| 5475 | UPDATE_ZFLAG(dst); | 5480 | UPDATE_ZFLAG(RD); |
| 5476 | 5481 | cpu->CFlag = carry; | |
| 5477 | if(rop >= !cpu->CFlag) | 5482 | cpu->VFlag = overflow; |
| 5478 | UPDATE_CFLAG_NOT_BORROW_FROM(rop - !cpu->CFlag, SHIFTER_OPERAND); | ||
| 5479 | else | ||
| 5480 | UPDATE_CFLAG_NOT_BORROW_FROM(rop, !cpu->CFlag); | ||
| 5481 | |||
| 5482 | UPDATE_VFLAG_OVERFLOW_FROM(dst, rop, lop); | ||
| 5483 | } | 5483 | } |
| 5484 | if (inst_cream->Rd == 15) { | 5484 | if (inst_cream->Rd == 15) { |
| 5485 | INC_PC(sizeof(sbc_inst)); | 5485 | INC_PC(sizeof(sbc_inst)); |
| @@ -6257,14 +6257,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 6257 | } | 6257 | } |
| 6258 | SUB_INST: | 6258 | SUB_INST: |
| 6259 | { | 6259 | { |
| 6260 | sub_inst *inst_cream = (sub_inst *)inst_base->component; | 6260 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 6261 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 6261 | sub_inst* const inst_cream = (sub_inst*)inst_base->component; |
| 6262 | lop = RN; | 6262 | |
| 6263 | if (inst_cream->Rn == 15) { | 6263 | u32 rn_val = RN; |
| 6264 | lop += 8; | 6264 | if (inst_cream->Rn == 15) |
| 6265 | } | 6265 | rn_val += 8; |
| 6266 | rop = SHIFTER_OPERAND; | 6266 | |
| 6267 | RD = dst = lop - rop; | 6267 | bool carry; |
| 6268 | bool overflow; | ||
| 6269 | RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow); | ||
| 6270 | |||
| 6268 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 6271 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 6269 | if (CurrentModeHasSPSR) { | 6272 | if (CurrentModeHasSPSR) { |
| 6270 | cpu->Cpsr = cpu->Spsr_copy; | 6273 | cpu->Cpsr = cpu->Spsr_copy; |
| @@ -6272,10 +6275,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 6272 | LOAD_NZCVT; | 6275 | LOAD_NZCVT; |
| 6273 | } | 6276 | } |
| 6274 | } else if (inst_cream->S) { | 6277 | } else if (inst_cream->S) { |
| 6275 | UPDATE_NFLAG(dst); | 6278 | UPDATE_NFLAG(RD); |
| 6276 | UPDATE_ZFLAG(dst); | 6279 | UPDATE_ZFLAG(RD); |
| 6277 | UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop); | 6280 | cpu->CFlag = carry; |
| 6278 | UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop); | 6281 | cpu->VFlag = overflow; |
| 6279 | } | 6282 | } |
| 6280 | if (inst_cream->Rd == 15) { | 6283 | if (inst_cream->Rd == 15) { |
| 6281 | INC_PC(sizeof(sub_inst)); | 6284 | INC_PC(sizeof(sub_inst)); |