diff options
| author | 2015-01-12 00:01:46 -0500 | |
|---|---|---|
| committer | 2015-01-12 00:44:28 -0500 | |
| commit | 9c2c89b7e1a93b52b53c567116b0d24bc4cb6ce7 (patch) | |
| tree | b436a7b0dfed383f339806b09452ad5207f513dc /src | |
| parent | Merge pull request #468 from lioncash/adc (diff) | |
| download | yuzu-9c2c89b7e1a93b52b53c567116b0d24bc4cb6ce7.tar.gz yuzu-9c2c89b7e1a93b52b53c567116b0d24bc4cb6ce7.tar.xz yuzu-9c2c89b7e1a93b52b53c567116b0d24bc4cb6ce7.zip | |
dyncom: Add a helper function for addition with a carry
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 21 | ||||
| -rw-r--r-- | src/core/arm/interpreter/armsupp.cpp | 16 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/armdefs.h | 1 |
3 files changed, 26 insertions, 12 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp index bf864c7a7..4c0a8f5cb 100644 --- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp +++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp | |||
| @@ -4003,16 +4003,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 4003 | } | 4003 | } |
| 4004 | ADC_INST: | 4004 | ADC_INST: |
| 4005 | { | 4005 | { |
| 4006 | adc_inst *inst_cream = (adc_inst *)inst_base->component; | 4006 | if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) { |
| 4007 | if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { | 4007 | adc_inst* const inst_cream = (adc_inst*)inst_base->component; |
| 4008 | u32 left = RN; | ||
| 4009 | u32 right = SHIFTER_OPERAND; | ||
| 4010 | 4008 | ||
| 4011 | u64 unsigned_sum = (left + right + cpu->CFlag); | 4009 | bool carry; |
| 4012 | s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)cpu->CFlag; | 4010 | bool overflow; |
| 4013 | u32 result = (unsigned_sum & 0xFFFFFFFF); | 4011 | RD = AddWithCarry(RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow); |
| 4014 | 4012 | ||
| 4015 | RD = result; | ||
| 4016 | if (inst_cream->S && (inst_cream->Rd == 15)) { | 4013 | if (inst_cream->S && (inst_cream->Rd == 15)) { |
| 4017 | if (CurrentModeHasSPSR) { | 4014 | if (CurrentModeHasSPSR) { |
| 4018 | cpu->Cpsr = cpu->Spsr_copy; | 4015 | cpu->Cpsr = cpu->Spsr_copy; |
| @@ -4020,10 +4017,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) { | |||
| 4020 | LOAD_NZCVT; | 4017 | LOAD_NZCVT; |
| 4021 | } | 4018 | } |
| 4022 | } else if (inst_cream->S) { | 4019 | } else if (inst_cream->S) { |
| 4023 | UPDATE_NFLAG(result); | 4020 | UPDATE_NFLAG(RD); |
| 4024 | UPDATE_ZFLAG(result); | 4021 | UPDATE_ZFLAG(RD); |
| 4025 | UPDATE_CFLAG_CARRY_FROM_ADD(left, right, cpu->CFlag); | 4022 | cpu->CFlag = carry; |
| 4026 | cpu->VFlag = ((s64)(s32)result != signed_sum); | 4023 | cpu->VFlag = overflow; |
| 4027 | } | 4024 | } |
| 4028 | if (inst_cream->Rd == 15) { | 4025 | if (inst_cream->Rd == 15) { |
| 4029 | INC_PC(sizeof(adc_inst)); | 4026 | INC_PC(sizeof(adc_inst)); |
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) | |||
| 418 | } | 418 | } |
| 419 | } | 419 | } |
| 420 | 420 | ||
| 421 | // Add with carry, indicates if a carry-out or signed overflow occurred. | ||
| 422 | u32 AddWithCarry(u32 left, u32 right, u32 carry_in, bool* carry_out_occurred, bool* overflow_occurred) | ||
| 423 | { | ||
| 424 | u64 unsigned_sum = (u64)left + (u64)right + (u64)carry_in; | ||
| 425 | s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)carry_in; | ||
| 426 | u64 result = (unsigned_sum & 0xFFFFFFFF); | ||
| 427 | |||
| 428 | if (carry_out_occurred) | ||
| 429 | *carry_out_occurred = (result != unsigned_sum); | ||
| 430 | |||
| 431 | if (overflow_occurred) | ||
| 432 | *overflow_occurred = ((s64)(s32)result != signed_sum); | ||
| 433 | |||
| 434 | return (u32)result; | ||
| 435 | } | ||
| 436 | |||
| 421 | // Compute whether an addition of A and B, giving RESULT, overflowed. | 437 | // Compute whether an addition of A and B, giving RESULT, overflowed. |
| 422 | bool AddOverflow(ARMword a, ARMword b, ARMword result) | 438 | bool AddOverflow(ARMword a, ARMword b, ARMword result) |
| 423 | { | 439 | { |
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); | |||
| 795 | extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...); | 795 | extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...); |
| 796 | extern void ARMul_SelectProcessor(ARMul_State*, unsigned); | 796 | extern void ARMul_SelectProcessor(ARMul_State*, unsigned); |
| 797 | 797 | ||
| 798 | extern u32 AddWithCarry(u32, u32, u32, bool*, bool*); | ||
| 798 | extern bool ARMul_AddOverflowQ(ARMword, ARMword); | 799 | extern bool ARMul_AddOverflowQ(ARMword, ARMword); |
| 799 | 800 | ||
| 800 | extern u8 ARMul_SignedSaturatedAdd8(u8, u8); | 801 | extern u8 ARMul_SignedSaturatedAdd8(u8, u8); |