summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Lioncash2015-01-12 00:01:46 -0500
committerGravatar Lioncash2015-01-12 00:44:28 -0500
commit9c2c89b7e1a93b52b53c567116b0d24bc4cb6ce7 (patch)
treeb436a7b0dfed383f339806b09452ad5207f513dc /src
parentMerge pull request #468 from lioncash/adc (diff)
downloadyuzu-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.cpp21
-rw-r--r--src/core/arm/interpreter/armsupp.cpp16
-rw-r--r--src/core/arm/skyeye_common/armdefs.h1
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.
422u32 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.
422bool AddOverflow(ARMword a, ARMword b, ARMword result) 438bool 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);
795extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...); 795extern void ARMul_ConsolePrint(ARMul_State*, const char*, ...);
796extern void ARMul_SelectProcessor(ARMul_State*, unsigned); 796extern void ARMul_SelectProcessor(ARMul_State*, unsigned);
797 797
798extern u32 AddWithCarry(u32, u32, u32, bool*, bool*);
798extern bool ARMul_AddOverflowQ(ARMword, ARMword); 799extern bool ARMul_AddOverflowQ(ARMword, ARMword);
799 800
800extern u8 ARMul_SignedSaturatedAdd8(u8, u8); 801extern u8 ARMul_SignedSaturatedAdd8(u8, u8);