ARM7: Fix flags on SBC/RSC
Jeffrey Pfau jeffrey@endrift.com
Fri, 20 May 2016 19:02:15 -0700
3 files changed,
21 insertions(+),
10 deletions(-)
M
CHANGES
→
CHANGES
@@ -24,6 +24,7 @@ - GBA Memory: Fix executing code from OBJ region of VRAM
- 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
M
src/arm/isa-arm.c
→
src/arm/isa-arm.c
@@ -184,8 +184,6 @@
// 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; \@@ -205,6 +203,17 @@ } else { \
cpu->cpsr.n = ARM_SIGN(D); \ cpu->cpsr.z = !(D); \ cpu->cpsr.c = ARM_BORROW_FROM(M, N, D); \ + 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); \ }@@ -454,14 +463,13 @@ DEFINE_ALU_INSTRUCTION_ARM(RSB, ARM_SUBTRACTION_S(cpu->shifterOperand, n, cpu->gprs[rd]),
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(RSC, ARM_SUBTRACTION_CARRY_S(cpu->shifterOperand, n, cpu->gprs[rd], !cpu->cpsr.c), + int32_t n = cpu->gprs[rn]; + cpu->gprs[rd] = cpu->shifterOperand - n - !cpu->cpsr.c;) -DEFINE_ALU_INSTRUCTION_ARM(SBC, ARM_SUBTRACTION_S(n, shifterOperand, cpu->gprs[rd]), +DEFINE_ALU_INSTRUCTION_ARM(SBC, ARM_SUBTRACTION_CARRY_S(n, cpu->shifterOperand, 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] = 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 @@ cpu->gprs[rdHi] = d >> 32;,
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 @@ cpu->gprs[rdHi] = cpu->gprs[rdHi] + (d >> 32) + ARM_CARRY_FROM(dm, dn, cpu->gprs[rd]);,
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]))
M
src/arm/isa-inlines.h
→
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))))