diff --git a/CHANGES b/CHANGES index 6639130c7..14a83d267 100644 --- a/CHANGES +++ b/CHANGES @@ -24,6 +24,7 @@ Bugfixes: - Util: Fix socket bind addresses - All: Fix instruction tables getting zeroed when linking sometimes - SDL: Fix SDL 1.2 build + - ARM7: Fix flags on SBC/RSC Misc: - GBA: Slightly optimize GBAProcessEvents - Qt: Add preset for DualShock 4 diff --git a/src/arm/isa-arm.c b/src/arm/isa-arm.c index bce24c608..61bae3163 100644 --- a/src/arm/isa-arm.c +++ b/src/arm/isa-arm.c @@ -184,8 +184,6 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) { // Instruction definitions // Beware pre-processor antics -#define NO_EXTEND64(V) (uint64_t)(uint32_t) (V) - #define ARM_ADDITION_S(M, N, D) \ if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \ cpu->cpsr = cpu->spsr; \ @@ -208,6 +206,17 @@ static inline void _immediate(struct ARMCore* cpu, uint32_t opcode) { cpu->cpsr.v = ARM_V_SUBTRACTION(M, N, D); \ } +#define ARM_SUBTRACTION_CARRY_S(M, N, D, C) \ + if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \ + cpu->cpsr = cpu->spsr; \ + _ARMReadCPSR(cpu); \ + } else { \ + cpu->cpsr.n = ARM_SIGN(D); \ + cpu->cpsr.z = !(D); \ + cpu->cpsr.c = ARM_BORROW_FROM_CARRY(M, N, D, C); \ + cpu->cpsr.v = ARM_V_SUBTRACTION(M, N, D); \ + } + #define ARM_NEUTRAL_S(M, N, D) \ if (rd == ARM_PC && _ARMModeHasSPSR(cpu->cpsr.priv)) { \ cpu->cpsr = cpu->spsr; \ @@ -454,14 +463,13 @@ DEFINE_ALU_INSTRUCTION_ARM(RSB, ARM_SUBTRACTION_S(cpu->shifterOperand, n, cpu->g int32_t n = cpu->gprs[rn]; cpu->gprs[rd] = cpu->shifterOperand - n;) -DEFINE_ALU_INSTRUCTION_ARM(RSC, ARM_SUBTRACTION_S(cpu->shifterOperand, n, cpu->gprs[rd]), - int32_t n = cpu->gprs[rn] + !cpu->cpsr.c; - cpu->gprs[rd] = cpu->shifterOperand - n;) - -DEFINE_ALU_INSTRUCTION_ARM(SBC, ARM_SUBTRACTION_S(n, shifterOperand, cpu->gprs[rd]), +DEFINE_ALU_INSTRUCTION_ARM(RSC, ARM_SUBTRACTION_CARRY_S(cpu->shifterOperand, n, cpu->gprs[rd], !cpu->cpsr.c), int32_t n = cpu->gprs[rn]; - int32_t shifterOperand = cpu->shifterOperand + !cpu->cpsr.c; - cpu->gprs[rd] = n - shifterOperand;) + cpu->gprs[rd] = cpu->shifterOperand - n - !cpu->cpsr.c;) + +DEFINE_ALU_INSTRUCTION_ARM(SBC, ARM_SUBTRACTION_CARRY_S(n, cpu->shifterOperand, cpu->gprs[rd], !cpu->cpsr.c), + int32_t n = cpu->gprs[rn]; + cpu->gprs[rd] = n - cpu->shifterOperand - !cpu->cpsr.c;) DEFINE_ALU_INSTRUCTION_ARM(SUB, ARM_SUBTRACTION_S(n, cpu->shifterOperand, cpu->gprs[rd]), int32_t n = cpu->gprs[rn]; @@ -495,7 +503,7 @@ DEFINE_MULTIPLY_INSTRUCTION_ARM(SMULL, ARM_NEUTRAL_HI_S(cpu->gprs[rd], cpu->gprs[rdHi])) DEFINE_MULTIPLY_INSTRUCTION_ARM(UMLAL, - uint64_t d = NO_EXTEND64(cpu->gprs[rm]) * NO_EXTEND64(cpu->gprs[rs]); + uint64_t d = ARM_UXT_64(cpu->gprs[rm]) * ARM_UXT_64(cpu->gprs[rs]); int32_t dm = cpu->gprs[rd]; int32_t dn = d; cpu->gprs[rd] = dm + dn; @@ -503,7 +511,7 @@ DEFINE_MULTIPLY_INSTRUCTION_ARM(UMLAL, ARM_NEUTRAL_HI_S(cpu->gprs[rd], cpu->gprs[rdHi])) DEFINE_MULTIPLY_INSTRUCTION_ARM(UMULL, - uint64_t d = NO_EXTEND64(cpu->gprs[rm]) * NO_EXTEND64(cpu->gprs[rs]); + uint64_t d = ARM_UXT_64(cpu->gprs[rm]) * ARM_UXT_64(cpu->gprs[rs]); cpu->gprs[rd] = d; cpu->gprs[rdHi] = d >> 32;, ARM_NEUTRAL_HI_S(cpu->gprs[rd], cpu->gprs[rdHi])) diff --git a/src/arm/isa-inlines.h b/src/arm/isa-inlines.h index 42a581b4a..5850dab69 100644 --- a/src/arm/isa-inlines.h +++ b/src/arm/isa-inlines.h @@ -29,9 +29,11 @@ #define ARM_SIGN(I) ((I) >> 31) #define ARM_SXT_8(I) (((int8_t) (I) << 24) >> 24) #define ARM_SXT_16(I) (((int16_t) (I) << 16) >> 16) +#define ARM_UXT_64(I) (uint64_t)(uint32_t) (I) #define ARM_CARRY_FROM(M, N, D) (((uint32_t) (M) >> 31) + ((uint32_t) (N) >> 31) > ((uint32_t) (D) >> 31)) #define ARM_BORROW_FROM(M, N, D) (((uint32_t) (M)) >= ((uint32_t) (N))) +#define ARM_BORROW_FROM_CARRY(M, N, D, C) (ARM_UXT_64(M) >= (ARM_UXT_64(N)) + (uint64_t) (C)) #define ARM_V_ADDITION(M, N, D) (!(ARM_SIGN((M) ^ (N))) && (ARM_SIGN((M) ^ (D))) && (ARM_SIGN((N) ^ (D)))) #define ARM_V_SUBTRACTION(M, N, D) ((ARM_SIGN((M) ^ (N))) && (ARM_SIGN((M) ^ (D))))