diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/arm/dyncom/arm_dyncom_interpreter.cpp | 305 | ||||
| -rw-r--r-- | src/core/arm/interpreter/armsupp.cpp | 16 | ||||
| -rw-r--r-- | src/core/arm/skyeye_common/armdefs.h | 1 |
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. | ||
| 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); |