summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/arm/dyncom/arm_dyncom_interpreter.cpp305
-rw-r--r--src/core/arm/interpreter/armsupp.cpp16
-rw-r--r--src/core/arm/skyeye_common/armdefs.h1
3 files changed, 175 insertions, 147 deletions
diff --git a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
index bf864c7a7..bae280b1c 100644
--- a/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
+++ b/src/core/arm/dyncom/arm_dyncom_interpreter.cpp
@@ -3967,16 +3967,12 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
3967 &&INIT_INST_LENGTH,&&END 3967 &&INIT_INST_LENGTH,&&END
3968 }; 3968 };
3969#endif 3969#endif
3970 arm_inst * inst_base; 3970 arm_inst* inst_base;
3971 unsigned int lop, rop, dst;
3972 unsigned int addr; 3971 unsigned int addr;
3973 unsigned int phys_addr; 3972 unsigned int phys_addr;
3974 unsigned int last_pc = 0;
3975 unsigned int num_instrs = 0; 3973 unsigned int num_instrs = 0;
3976 3974
3977 static unsigned int last_physical_base = 0, last_logical_base = 0;
3978 int ptr; 3975 int ptr;
3979 bool single_step = (cpu->NumInstrsToExecute == 1);
3980 3976
3981 LOAD_NZCVT; 3977 LOAD_NZCVT;
3982 DISPATCH: 3978 DISPATCH:
@@ -4003,16 +3999,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4003 } 3999 }
4004 ADC_INST: 4000 ADC_INST:
4005 { 4001 {
4006 adc_inst *inst_cream = (adc_inst *)inst_base->component; 4002 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
4007 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4003 adc_inst* const inst_cream = (adc_inst*)inst_base->component;
4008 u32 left = RN;
4009 u32 right = SHIFTER_OPERAND;
4010 4004
4011 u64 unsigned_sum = (left + right + cpu->CFlag); 4005 bool carry;
4012 s64 signed_sum = (s64)(s32)left + (s64)(s32)right + (s64)cpu->CFlag; 4006 bool overflow;
4013 u32 result = (unsigned_sum & 0xFFFFFFFF); 4007 RD = AddWithCarry(RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
4014 4008
4015 RD = result;
4016 if (inst_cream->S && (inst_cream->Rd == 15)) { 4009 if (inst_cream->S && (inst_cream->Rd == 15)) {
4017 if (CurrentModeHasSPSR) { 4010 if (CurrentModeHasSPSR) {
4018 cpu->Cpsr = cpu->Spsr_copy; 4011 cpu->Cpsr = cpu->Spsr_copy;
@@ -4020,10 +4013,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4020 LOAD_NZCVT; 4013 LOAD_NZCVT;
4021 } 4014 }
4022 } else if (inst_cream->S) { 4015 } else if (inst_cream->S) {
4023 UPDATE_NFLAG(result); 4016 UPDATE_NFLAG(RD);
4024 UPDATE_ZFLAG(result); 4017 UPDATE_ZFLAG(RD);
4025 UPDATE_CFLAG_CARRY_FROM_ADD(left, right, cpu->CFlag); 4018 cpu->CFlag = carry;
4026 cpu->VFlag = ((s64)(s32)result != signed_sum); 4019 cpu->VFlag = overflow;
4027 } 4020 }
4028 if (inst_cream->Rd == 15) { 4021 if (inst_cream->Rd == 15) {
4029 INC_PC(sizeof(adc_inst)); 4022 INC_PC(sizeof(adc_inst));
@@ -4037,14 +4030,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4037 } 4030 }
4038 ADD_INST: 4031 ADD_INST:
4039 { 4032 {
4040 add_inst *inst_cream = (add_inst *)inst_base->component; 4033 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
4041 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4034 add_inst* const inst_cream = (add_inst*)inst_base->component;
4042 lop = RN; 4035
4043 if (inst_cream->Rn == 15) { 4036 u32 rn_val = RN;
4044 lop += 2 * GET_INST_SIZE(cpu); 4037 if (inst_cream->Rn == 15)
4045 } 4038 rn_val += 2 * GET_INST_SIZE(cpu);
4046 rop = SHIFTER_OPERAND; 4039
4047 RD = dst = lop + rop; 4040 bool carry;
4041 bool overflow;
4042 RD = AddWithCarry(rn_val, SHIFTER_OPERAND, 0, &carry, &overflow);
4043
4048 if (inst_cream->S && (inst_cream->Rd == 15)) { 4044 if (inst_cream->S && (inst_cream->Rd == 15)) {
4049 if (CurrentModeHasSPSR) { 4045 if (CurrentModeHasSPSR) {
4050 cpu->Cpsr = cpu->Spsr_copy; 4046 cpu->Cpsr = cpu->Spsr_copy;
@@ -4052,10 +4048,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4052 LOAD_NZCVT; 4048 LOAD_NZCVT;
4053 } 4049 }
4054 } else if (inst_cream->S) { 4050 } else if (inst_cream->S) {
4055 UPDATE_NFLAG(dst); 4051 UPDATE_NFLAG(RD);
4056 UPDATE_ZFLAG(dst); 4052 UPDATE_ZFLAG(RD);
4057 UPDATE_CFLAG(dst, lop, rop); 4053 cpu->CFlag = carry;
4058 UPDATE_VFLAG((int)dst, (int)lop, (int)rop); 4054 cpu->VFlag = overflow;
4059 } 4055 }
4060 if (inst_cream->Rd == 15) { 4056 if (inst_cream->Rd == 15) {
4061 INC_PC(sizeof(add_inst)); 4057 INC_PC(sizeof(add_inst));
@@ -4071,9 +4067,9 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4071 { 4067 {
4072 and_inst *inst_cream = (and_inst *)inst_base->component; 4068 and_inst *inst_cream = (and_inst *)inst_base->component;
4073 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4069 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4074 lop = RN; 4070 u32 lop = RN;
4075 rop = SHIFTER_OPERAND; 4071 u32 rop = SHIFTER_OPERAND;
4076 RD = dst = lop & rop; 4072 RD = lop & rop;
4077 if (inst_cream->S && (inst_cream->Rd == 15)) { 4073 if (inst_cream->S && (inst_cream->Rd == 15)) {
4078 if (CurrentModeHasSPSR) { 4074 if (CurrentModeHasSPSR) {
4079 cpu->Cpsr = cpu->Spsr_copy; 4075 cpu->Cpsr = cpu->Spsr_copy;
@@ -4081,8 +4077,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4081 LOAD_NZCVT; 4077 LOAD_NZCVT;
4082 } 4078 }
4083 } else if (inst_cream->S) { 4079 } else if (inst_cream->S) {
4084 UPDATE_NFLAG(dst); 4080 UPDATE_NFLAG(RD);
4085 UPDATE_ZFLAG(dst); 4081 UPDATE_ZFLAG(RD);
4086 UPDATE_CFLAG_WITH_SC; 4082 UPDATE_CFLAG_WITH_SC;
4087 } 4083 }
4088 if (inst_cream->Rd == 15) { 4084 if (inst_cream->Rd == 15) {
@@ -4114,12 +4110,12 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4114 { 4110 {
4115 bic_inst *inst_cream = (bic_inst *)inst_base->component; 4111 bic_inst *inst_cream = (bic_inst *)inst_base->component;
4116 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4112 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4117 lop = RN; 4113 u32 lop = RN;
4118 if (inst_cream->Rn == 15) { 4114 if (inst_cream->Rn == 15) {
4119 lop += 2 * GET_INST_SIZE(cpu); 4115 lop += 2 * GET_INST_SIZE(cpu);
4120 } 4116 }
4121 rop = SHIFTER_OPERAND; 4117 u32 rop = SHIFTER_OPERAND;
4122 RD = dst = lop & (~rop); 4118 RD = lop & (~rop);
4123 if ((inst_cream->S) && (inst_cream->Rd == 15)) { 4119 if ((inst_cream->S) && (inst_cream->Rd == 15)) {
4124 if (CurrentModeHasSPSR) { 4120 if (CurrentModeHasSPSR) {
4125 cpu->Cpsr = cpu->Spsr_copy; 4121 cpu->Cpsr = cpu->Spsr_copy;
@@ -4127,8 +4123,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4127 LOAD_NZCVT; 4123 LOAD_NZCVT;
4128 } 4124 }
4129 } else if (inst_cream->S) { 4125 } else if (inst_cream->S) {
4130 UPDATE_NFLAG(dst); 4126 UPDATE_NFLAG(RD);
4131 UPDATE_ZFLAG(dst); 4127 UPDATE_ZFLAG(RD);
4132 UPDATE_CFLAG_WITH_SC; 4128 UPDATE_CFLAG_WITH_SC;
4133 } 4129 }
4134 if (inst_cream->Rd == 15) { 4130 if (inst_cream->Rd == 15) {
@@ -4234,15 +4230,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4234 } 4230 }
4235 CMN_INST: 4231 CMN_INST:
4236 { 4232 {
4237 cmn_inst *inst_cream = (cmn_inst *)inst_base->component; 4233 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
4238 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4234 cmn_inst* const inst_cream = (cmn_inst*)inst_base->component;
4239 lop = RN; 4235
4240 rop = SHIFTER_OPERAND; 4236 bool carry;
4241 dst = lop + rop; 4237 bool overflow;
4242 UPDATE_NFLAG(dst); 4238 u32 result = AddWithCarry(RN, SHIFTER_OPERAND, 0, &carry, &overflow);
4243 UPDATE_ZFLAG(dst); 4239
4244 UPDATE_CFLAG(dst, lop, rop); 4240 UPDATE_NFLAG(result);
4245 UPDATE_VFLAG((int)dst, (int)lop, (int)rop); 4241 UPDATE_ZFLAG(result);
4242 cpu->CFlag = carry;
4243 cpu->VFlag = overflow;
4246 } 4244 }
4247 cpu->Reg[15] += GET_INST_SIZE(cpu); 4245 cpu->Reg[15] += GET_INST_SIZE(cpu);
4248 INC_PC(sizeof(cmn_inst)); 4246 INC_PC(sizeof(cmn_inst));
@@ -4251,19 +4249,21 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4251 } 4249 }
4252 CMP_INST: 4250 CMP_INST:
4253 { 4251 {
4254 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4252 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
4255 cmp_inst *inst_cream = (cmp_inst *)inst_base->component; 4253 cmp_inst* const inst_cream = (cmp_inst*)inst_base->component;
4256 lop = RN;
4257 if (inst_cream->Rn == 15) {
4258 lop += 2 * GET_INST_SIZE(cpu);
4259 }
4260 rop = SHIFTER_OPERAND;
4261 dst = lop - rop;
4262 4254
4263 UPDATE_NFLAG(dst); 4255 u32 rn_val = RN;
4264 UPDATE_ZFLAG(dst); 4256 if (inst_cream->Rn == 15)
4265 UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop); 4257 rn_val += 2 * GET_INST_SIZE(cpu);
4266 UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop); 4258
4259 bool carry;
4260 bool overflow;
4261 u32 result = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
4262
4263 UPDATE_NFLAG(result);
4264 UPDATE_ZFLAG(result);
4265 cpu->CFlag = carry;
4266 cpu->VFlag = overflow;
4267 } 4267 }
4268 cpu->Reg[15] += GET_INST_SIZE(cpu); 4268 cpu->Reg[15] += GET_INST_SIZE(cpu);
4269 INC_PC(sizeof(cmp_inst)); 4269 INC_PC(sizeof(cmp_inst));
@@ -4321,12 +4321,12 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4321 { 4321 {
4322 eor_inst *inst_cream = (eor_inst *)inst_base->component; 4322 eor_inst *inst_cream = (eor_inst *)inst_base->component;
4323 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4323 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4324 lop = RN; 4324 u32 lop = RN;
4325 if (inst_cream->Rn == 15) { 4325 if (inst_cream->Rn == 15) {
4326 lop += 2 * GET_INST_SIZE(cpu); 4326 lop += 2 * GET_INST_SIZE(cpu);
4327 } 4327 }
4328 rop = SHIFTER_OPERAND; 4328 u32 rop = SHIFTER_OPERAND;
4329 RD = dst = lop ^ rop; 4329 RD = lop ^ rop;
4330 if (inst_cream->S && (inst_cream->Rd == 15)) { 4330 if (inst_cream->S && (inst_cream->Rd == 15)) {
4331 if (CurrentModeHasSPSR) { 4331 if (CurrentModeHasSPSR) {
4332 cpu->Cpsr = cpu->Spsr_copy; 4332 cpu->Cpsr = cpu->Spsr_copy;
@@ -4334,8 +4334,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4334 LOAD_NZCVT; 4334 LOAD_NZCVT;
4335 } 4335 }
4336 } else if (inst_cream->S) { 4336 } else if (inst_cream->S) {
4337 UPDATE_NFLAG(dst); 4337 UPDATE_NFLAG(RD);
4338 UPDATE_ZFLAG(dst); 4338 UPDATE_ZFLAG(RD);
4339 UPDATE_CFLAG_WITH_SC; 4339 UPDATE_CFLAG_WITH_SC;
4340 } 4340 }
4341 if (inst_cream->Rd == 15) { 4341 if (inst_cream->Rd == 15) {
@@ -4852,10 +4852,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4852 LOG_ERROR(Core_ARM11, "invalid operands for MLA"); 4852 LOG_ERROR(Core_ARM11, "invalid operands for MLA");
4853 CITRA_IGNORE_EXIT(-1); 4853 CITRA_IGNORE_EXIT(-1);
4854 } 4854 }
4855 RD = dst = static_cast<uint32_t>((rm * rs + rn) & 0xffffffff); 4855 RD = static_cast<uint32_t>((rm * rs + rn) & 0xffffffff);
4856 if (inst_cream->S) { 4856 if (inst_cream->S) {
4857 UPDATE_NFLAG(dst); 4857 UPDATE_NFLAG(RD);
4858 UPDATE_ZFLAG(dst); 4858 UPDATE_ZFLAG(RD);
4859 } 4859 }
4860 if (inst_cream->Rd == 15) { 4860 if (inst_cream->Rd == 15) {
4861 INC_PC(sizeof(mla_inst)); 4861 INC_PC(sizeof(mla_inst));
@@ -4871,7 +4871,7 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4871 { 4871 {
4872 mov_inst *inst_cream = (mov_inst *)inst_base->component; 4872 mov_inst *inst_cream = (mov_inst *)inst_base->component;
4873 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 4873 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
4874 RD = dst = SHIFTER_OPERAND; 4874 RD = SHIFTER_OPERAND;
4875 if (inst_cream->S && (inst_cream->Rd == 15)) { 4875 if (inst_cream->S && (inst_cream->Rd == 15)) {
4876 if (CurrentModeHasSPSR) { 4876 if (CurrentModeHasSPSR) {
4877 cpu->Cpsr = cpu->Spsr_copy; 4877 cpu->Cpsr = cpu->Spsr_copy;
@@ -4879,8 +4879,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
4879 LOAD_NZCVT; 4879 LOAD_NZCVT;
4880 } 4880 }
4881 } else if (inst_cream->S) { 4881 } else if (inst_cream->S) {
4882 UPDATE_NFLAG(dst); 4882 UPDATE_NFLAG(RD);
4883 UPDATE_ZFLAG(dst); 4883 UPDATE_ZFLAG(RD);
4884 UPDATE_CFLAG_WITH_SC; 4884 UPDATE_CFLAG_WITH_SC;
4885 } 4885 }
4886 if (inst_cream->Rd == 15) { 4886 if (inst_cream->Rd == 15) {
@@ -5016,10 +5016,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5016 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5016 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) {
5017 uint64_t rm = RM; 5017 uint64_t rm = RM;
5018 uint64_t rs = RS; 5018 uint64_t rs = RS;
5019 RD = dst = static_cast<uint32_t>((rm * rs) & 0xffffffff); 5019 RD = static_cast<uint32_t>((rm * rs) & 0xffffffff);
5020 if (inst_cream->S) { 5020 if (inst_cream->S) {
5021 UPDATE_NFLAG(dst); 5021 UPDATE_NFLAG(RD);
5022 UPDATE_ZFLAG(dst); 5022 UPDATE_ZFLAG(RD);
5023 } 5023 }
5024 if (inst_cream->Rd == 15) { 5024 if (inst_cream->Rd == 15) {
5025 INC_PC(sizeof(mul_inst)); 5025 INC_PC(sizeof(mul_inst));
@@ -5033,9 +5033,11 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5033 } 5033 }
5034 MVN_INST: 5034 MVN_INST:
5035 { 5035 {
5036 mvn_inst *inst_cream = (mvn_inst *)inst_base->component; 5036 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5037 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5037 mvn_inst* const inst_cream = (mvn_inst*)inst_base->component;
5038 RD = dst = ~SHIFTER_OPERAND; 5038
5039 RD = ~SHIFTER_OPERAND;
5040
5039 if (inst_cream->S && (inst_cream->Rd == 15)) { 5041 if (inst_cream->S && (inst_cream->Rd == 15)) {
5040 if (CurrentModeHasSPSR) { 5042 if (CurrentModeHasSPSR) {
5041 cpu->Cpsr = cpu->Spsr_copy; 5043 cpu->Cpsr = cpu->Spsr_copy;
@@ -5043,8 +5045,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5043 LOAD_NZCVT; 5045 LOAD_NZCVT;
5044 } 5046 }
5045 } else if (inst_cream->S) { 5047 } else if (inst_cream->S) {
5046 UPDATE_NFLAG(dst); 5048 UPDATE_NFLAG(RD);
5047 UPDATE_ZFLAG(dst); 5049 UPDATE_ZFLAG(RD);
5048 UPDATE_CFLAG_WITH_SC; 5050 UPDATE_CFLAG_WITH_SC;
5049 } 5051 }
5050 if (inst_cream->Rd == 15) { 5052 if (inst_cream->Rd == 15) {
@@ -5059,11 +5061,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5059 } 5061 }
5060 ORR_INST: 5062 ORR_INST:
5061 { 5063 {
5062 orr_inst *inst_cream = (orr_inst *)inst_base->component; 5064 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5063 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5065 orr_inst* const inst_cream = (orr_inst*)inst_base->component;
5064 lop = RN; 5066
5065 rop = SHIFTER_OPERAND; 5067 u32 lop = RN;
5066 RD = dst = lop | rop; 5068 u32 rop = SHIFTER_OPERAND;
5069 RD = lop | rop;
5070
5067 if (inst_cream->S && (inst_cream->Rd == 15)) { 5071 if (inst_cream->S && (inst_cream->Rd == 15)) {
5068 if (CurrentModeHasSPSR) { 5072 if (CurrentModeHasSPSR) {
5069 cpu->Cpsr = cpu->Spsr_copy; 5073 cpu->Cpsr = cpu->Spsr_copy;
@@ -5071,8 +5075,8 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5071 LOAD_NZCVT; 5075 LOAD_NZCVT;
5072 } 5076 }
5073 } else if (inst_cream->S) { 5077 } else if (inst_cream->S) {
5074 UPDATE_NFLAG(dst); 5078 UPDATE_NFLAG(RD);
5075 UPDATE_ZFLAG(dst); 5079 UPDATE_ZFLAG(RD);
5076 UPDATE_CFLAG_WITH_SC; 5080 UPDATE_CFLAG_WITH_SC;
5077 } 5081 }
5078 if (inst_cream->Rd == 15) { 5082 if (inst_cream->Rd == 15) {
@@ -5292,14 +5296,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5292 RFE_INST: 5296 RFE_INST:
5293 RSB_INST: 5297 RSB_INST:
5294 { 5298 {
5295 rsb_inst *inst_cream = (rsb_inst *)inst_base->component; 5299 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5296 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5300 rsb_inst* const inst_cream = (rsb_inst*)inst_base->component;
5297 rop = RN; 5301
5298 lop = SHIFTER_OPERAND; 5302 u32 rn_val = RN;
5299 if (inst_cream->Rn == 15) { 5303 if (inst_cream->Rn == 15)
5300 rop += 2 * GET_INST_SIZE(cpu);; 5304 rn_val += 2 * GET_INST_SIZE(cpu);
5301 } 5305
5302 RD = dst = lop - rop; 5306 bool carry;
5307 bool overflow;
5308 RD = AddWithCarry(~rn_val, SHIFTER_OPERAND, 1, &carry, &overflow);
5309
5303 if (inst_cream->S && (inst_cream->Rd == 15)) { 5310 if (inst_cream->S && (inst_cream->Rd == 15)) {
5304 if (CurrentModeHasSPSR) { 5311 if (CurrentModeHasSPSR) {
5305 cpu->Cpsr = cpu->Spsr_copy; 5312 cpu->Cpsr = cpu->Spsr_copy;
@@ -5307,10 +5314,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5307 LOAD_NZCVT; 5314 LOAD_NZCVT;
5308 } 5315 }
5309 } else if (inst_cream->S) { 5316 } else if (inst_cream->S) {
5310 UPDATE_NFLAG(dst); 5317 UPDATE_NFLAG(RD);
5311 UPDATE_ZFLAG(dst); 5318 UPDATE_ZFLAG(RD);
5312 UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop); 5319 cpu->CFlag = carry;
5313 UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop); 5320 cpu->VFlag = overflow;
5314 } 5321 }
5315 if (inst_cream->Rd == 15) { 5322 if (inst_cream->Rd == 15) {
5316 INC_PC(sizeof(rsb_inst)); 5323 INC_PC(sizeof(rsb_inst));
@@ -5324,11 +5331,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5324 } 5331 }
5325 RSC_INST: 5332 RSC_INST:
5326 { 5333 {
5327 rsc_inst *inst_cream = (rsc_inst *)inst_base->component; 5334 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5328 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5335 rsc_inst* const inst_cream = (rsc_inst*)inst_base->component;
5329 lop = RN; 5336
5330 rop = SHIFTER_OPERAND; 5337 bool carry;
5331 RD = dst = rop - lop - !cpu->CFlag; 5338 bool overflow;
5339 RD = AddWithCarry(~RN, SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
5340
5332 if (inst_cream->S && (inst_cream->Rd == 15)) { 5341 if (inst_cream->S && (inst_cream->Rd == 15)) {
5333 if (CurrentModeHasSPSR) { 5342 if (CurrentModeHasSPSR) {
5334 cpu->Cpsr = cpu->Spsr_copy; 5343 cpu->Cpsr = cpu->Spsr_copy;
@@ -5336,10 +5345,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5336 LOAD_NZCVT; 5345 LOAD_NZCVT;
5337 } 5346 }
5338 } else if (inst_cream->S) { 5347 } else if (inst_cream->S) {
5339 UPDATE_NFLAG(dst); 5348 UPDATE_NFLAG(RD);
5340 UPDATE_ZFLAG(dst); 5349 UPDATE_ZFLAG(RD);
5341 UPDATE_CFLAG_NOT_BORROW_FROM_FLAG(rop, lop, !cpu->CFlag); 5350 cpu->CFlag = carry;
5342 UPDATE_VFLAG_OVERFLOW_FROM((int)dst, (int)rop, (int)lop); 5351 cpu->VFlag = overflow;
5343 } 5352 }
5344 if (inst_cream->Rd == 15) { 5353 if (inst_cream->Rd == 15) {
5345 INC_PC(sizeof(rsc_inst)); 5354 INC_PC(sizeof(rsc_inst));
@@ -5462,11 +5471,13 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5462 5471
5463 SBC_INST: 5472 SBC_INST:
5464 { 5473 {
5465 sbc_inst *inst_cream = (sbc_inst *)inst_base->component; 5474 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
5466 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 5475 sbc_inst* const inst_cream = (sbc_inst*)inst_base->component;
5467 lop = SHIFTER_OPERAND + !cpu->CFlag; 5476
5468 rop = RN; 5477 bool carry;
5469 RD = dst = rop - lop; 5478 bool overflow;
5479 RD = AddWithCarry(RN, ~SHIFTER_OPERAND, cpu->CFlag, &carry, &overflow);
5480
5470 if (inst_cream->S && (inst_cream->Rd == 15)) { 5481 if (inst_cream->S && (inst_cream->Rd == 15)) {
5471 if (CurrentModeHasSPSR) { 5482 if (CurrentModeHasSPSR) {
5472 cpu->Cpsr = cpu->Spsr_copy; 5483 cpu->Cpsr = cpu->Spsr_copy;
@@ -5474,15 +5485,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
5474 LOAD_NZCVT; 5485 LOAD_NZCVT;
5475 } 5486 }
5476 } else if (inst_cream->S) { 5487 } else if (inst_cream->S) {
5477 UPDATE_NFLAG(dst); 5488 UPDATE_NFLAG(RD);
5478 UPDATE_ZFLAG(dst); 5489 UPDATE_ZFLAG(RD);
5479 5490 cpu->CFlag = carry;
5480 if(rop >= !cpu->CFlag) 5491 cpu->VFlag = overflow;
5481 UPDATE_CFLAG_NOT_BORROW_FROM(rop - !cpu->CFlag, SHIFTER_OPERAND);
5482 else
5483 UPDATE_CFLAG_NOT_BORROW_FROM(rop, !cpu->CFlag);
5484
5485 UPDATE_VFLAG_OVERFLOW_FROM(dst, rop, lop);
5486 } 5492 }
5487 if (inst_cream->Rd == 15) { 5493 if (inst_cream->Rd == 15) {
5488 INC_PC(sizeof(sbc_inst)); 5494 INC_PC(sizeof(sbc_inst));
@@ -6260,14 +6266,17 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6260 } 6266 }
6261 SUB_INST: 6267 SUB_INST:
6262 { 6268 {
6263 sub_inst *inst_cream = (sub_inst *)inst_base->component; 6269 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
6264 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 6270 sub_inst* const inst_cream = (sub_inst*)inst_base->component;
6265 lop = RN; 6271
6266 if (inst_cream->Rn == 15) { 6272 u32 rn_val = RN;
6267 lop += 8; 6273 if (inst_cream->Rn == 15)
6268 } 6274 rn_val += 8;
6269 rop = SHIFTER_OPERAND; 6275
6270 RD = dst = lop - rop; 6276 bool carry;
6277 bool overflow;
6278 RD = AddWithCarry(rn_val, ~SHIFTER_OPERAND, 1, &carry, &overflow);
6279
6271 if (inst_cream->S && (inst_cream->Rd == 15)) { 6280 if (inst_cream->S && (inst_cream->Rd == 15)) {
6272 if (CurrentModeHasSPSR) { 6281 if (CurrentModeHasSPSR) {
6273 cpu->Cpsr = cpu->Spsr_copy; 6282 cpu->Cpsr = cpu->Spsr_copy;
@@ -6275,10 +6284,10 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6275 LOAD_NZCVT; 6284 LOAD_NZCVT;
6276 } 6285 }
6277 } else if (inst_cream->S) { 6286 } else if (inst_cream->S) {
6278 UPDATE_NFLAG(dst); 6287 UPDATE_NFLAG(RD);
6279 UPDATE_ZFLAG(dst); 6288 UPDATE_ZFLAG(RD);
6280 UPDATE_CFLAG_NOT_BORROW_FROM(lop, rop); 6289 cpu->CFlag = carry;
6281 UPDATE_VFLAG_OVERFLOW_FROM(dst, lop, rop); 6290 cpu->VFlag = overflow;
6282 } 6291 }
6283 if (inst_cream->Rd == 15) { 6292 if (inst_cream->Rd == 15) {
6284 INC_PC(sizeof(sub_inst)); 6293 INC_PC(sizeof(sub_inst));
@@ -6406,18 +6415,19 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6406 6415
6407 TEQ_INST: 6416 TEQ_INST:
6408 { 6417 {
6409 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 6418 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
6410 teq_inst *inst_cream = (teq_inst *)inst_base->component; 6419 teq_inst* const inst_cream = (teq_inst*)inst_base->component;
6411 lop = RN; 6420
6421 u32 lop = RN;
6422 u32 rop = SHIFTER_OPERAND;
6412 6423
6413 if (inst_cream->Rn == 15) 6424 if (inst_cream->Rn == 15)
6414 lop += GET_INST_SIZE(cpu) * 2; 6425 lop += GET_INST_SIZE(cpu) * 2;
6415 6426
6416 rop = SHIFTER_OPERAND; 6427 u32 result = lop ^ rop;
6417 dst = lop ^ rop;
6418 6428
6419 UPDATE_NFLAG(dst); 6429 UPDATE_NFLAG(result);
6420 UPDATE_ZFLAG(dst); 6430 UPDATE_ZFLAG(result);
6421 UPDATE_CFLAG_WITH_SC; 6431 UPDATE_CFLAG_WITH_SC;
6422 } 6432 }
6423 cpu->Reg[15] += GET_INST_SIZE(cpu); 6433 cpu->Reg[15] += GET_INST_SIZE(cpu);
@@ -6427,18 +6437,19 @@ unsigned InterpreterMainLoop(ARMul_State* state) {
6427 } 6437 }
6428 TST_INST: 6438 TST_INST:
6429 { 6439 {
6430 if ((inst_base->cond == 0xe) || CondPassed(cpu, inst_base->cond)) { 6440 if (inst_base->cond == 0xE || CondPassed(cpu, inst_base->cond)) {
6431 tst_inst *inst_cream = (tst_inst *)inst_base->component; 6441 tst_inst* const inst_cream = (tst_inst*)inst_base->component;
6432 lop = RN; 6442
6443 u32 lop = RN;
6444 u32 rop = SHIFTER_OPERAND;
6433 6445
6434 if (inst_cream->Rn == 15) 6446 if (inst_cream->Rn == 15)
6435 lop += GET_INST_SIZE(cpu) * 2; 6447 lop += GET_INST_SIZE(cpu) * 2;
6436 6448
6437 rop = SHIFTER_OPERAND; 6449 u32 result = lop & rop;
6438 dst = lop & rop;
6439 6450
6440 UPDATE_NFLAG(dst); 6451 UPDATE_NFLAG(result);
6441 UPDATE_ZFLAG(dst); 6452 UPDATE_ZFLAG(result);
6442 UPDATE_CFLAG_WITH_SC; 6453 UPDATE_CFLAG_WITH_SC;
6443 } 6454 }
6444 cpu->Reg[15] += GET_INST_SIZE(cpu); 6455 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)
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);