all repos — mgba @ 27882fbded835ca52b6b128da57b12e23cf715ba

mGBA Game Boy Advance Emulator

ARM: Fix ALU reading PC after shifting
Vicki Pfau vi@endrift.com
Fri, 24 Jan 2020 01:46:15 -0800
commit

27882fbded835ca52b6b128da57b12e23cf715ba

parent

8b9cd78d0f1451cec0cc560dfa17c27ca06420a0

2 files changed, 23 insertions(+), 25 deletions(-)

jump to
M CHANGESCHANGES

@@ -1,5 +1,6 @@

0.9.0: (Future) Emulation fixes: + - ARM: Fix ALU reading PC after shifting - GBA Memory: Misaligned SRAM writes are ignored Other fixes: - Qt: Only dynamically reset video scale if a game is running
M src/arm/isa-arm.csrc/arm/isa-arm.c

@@ -302,7 +302,10 @@ #define DEFINE_ALU_INSTRUCTION_EX_ARM(NAME, S_BODY, SHIFTER, BODY) \

DEFINE_INSTRUCTION_ARM(NAME, \ int rd = (opcode >> 12) & 0xF; \ int rn = (opcode >> 16) & 0xF; \ - UNUSED(rn); \ + int32_t n = cpu->gprs[rn]; \ + if (UNLIKELY(rn == ARM_PC && (opcode & 0x02000010) == 0x00000010)) { \ + n += WORD_SIZE_ARM; \ + } \ SHIFTER(cpu, opcode); \ BODY; \ S_BODY; \

@@ -465,58 +468,52 @@

// Begin ALU definitions DEFINE_ALU_INSTRUCTION_ARM(ADD, ARM_ADDITION_S(n, cpu->shifterOperand, cpu->gprs[rd]), - int32_t n = cpu->gprs[rn]; cpu->gprs[rd] = n + cpu->shifterOperand;) DEFINE_ALU_INSTRUCTION_ARM(ADC, ARM_ADDITION_S(n, cpu->shifterOperand, cpu->gprs[rd]), - int32_t n = cpu->gprs[rn]; cpu->gprs[rd] = n + cpu->shifterOperand + cpu->cpsr.c;) -DEFINE_ALU_INSTRUCTION_ARM(AND, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), - cpu->gprs[rd] = cpu->gprs[rn] & cpu->shifterOperand;) +DEFINE_ALU_INSTRUCTION_ARM(AND, ARM_NEUTRAL_S(n, cpu->shifterOperand, cpu->gprs[rd]), + cpu->gprs[rd] = n & cpu->shifterOperand;) -DEFINE_ALU_INSTRUCTION_ARM(BIC, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), - cpu->gprs[rd] = cpu->gprs[rn] & ~cpu->shifterOperand;) +DEFINE_ALU_INSTRUCTION_ARM(BIC, ARM_NEUTRAL_S(n, cpu->shifterOperand, cpu->gprs[rd]), + cpu->gprs[rd] = n & ~cpu->shifterOperand;) -DEFINE_ALU_INSTRUCTION_S_ONLY_ARM(CMN, ARM_ADDITION_S(cpu->gprs[rn], cpu->shifterOperand, aluOut), - int32_t aluOut = cpu->gprs[rn] + cpu->shifterOperand;) +DEFINE_ALU_INSTRUCTION_S_ONLY_ARM(CMN, ARM_ADDITION_S(n, cpu->shifterOperand, aluOut), + int32_t aluOut = n + cpu->shifterOperand;) -DEFINE_ALU_INSTRUCTION_S_ONLY_ARM(CMP, ARM_SUBTRACTION_S(cpu->gprs[rn], cpu->shifterOperand, aluOut), - int32_t aluOut = cpu->gprs[rn] - cpu->shifterOperand;) +DEFINE_ALU_INSTRUCTION_S_ONLY_ARM(CMP, ARM_SUBTRACTION_S(n, cpu->shifterOperand, aluOut), + int32_t aluOut = n - cpu->shifterOperand;) -DEFINE_ALU_INSTRUCTION_ARM(EOR, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), - cpu->gprs[rd] = cpu->gprs[rn] ^ cpu->shifterOperand;) +DEFINE_ALU_INSTRUCTION_ARM(EOR, ARM_NEUTRAL_S(n, cpu->shifterOperand, cpu->gprs[rd]), + cpu->gprs[rd] = n ^ cpu->shifterOperand;) -DEFINE_ALU_INSTRUCTION_ARM(MOV, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), +DEFINE_ALU_INSTRUCTION_ARM(MOV, ARM_NEUTRAL_S(n, cpu->shifterOperand, cpu->gprs[rd]), cpu->gprs[rd] = cpu->shifterOperand;) -DEFINE_ALU_INSTRUCTION_ARM(MVN, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), +DEFINE_ALU_INSTRUCTION_ARM(MVN, ARM_NEUTRAL_S(n, cpu->shifterOperand, cpu->gprs[rd]), cpu->gprs[rd] = ~cpu->shifterOperand;) -DEFINE_ALU_INSTRUCTION_ARM(ORR, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, cpu->gprs[rd]), - cpu->gprs[rd] = cpu->gprs[rn] | cpu->shifterOperand;) +DEFINE_ALU_INSTRUCTION_ARM(ORR, ARM_NEUTRAL_S(n, cpu->shifterOperand, cpu->gprs[rd]), + cpu->gprs[rd] = n | cpu->shifterOperand;) 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_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_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]; cpu->gprs[rd] = n - cpu->shifterOperand;) -DEFINE_ALU_INSTRUCTION_S_ONLY_ARM(TEQ, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, aluOut), - int32_t aluOut = cpu->gprs[rn] ^ cpu->shifterOperand;) +DEFINE_ALU_INSTRUCTION_S_ONLY_ARM(TEQ, ARM_NEUTRAL_S(n, cpu->shifterOperand, aluOut), + int32_t aluOut = n ^ cpu->shifterOperand;) -DEFINE_ALU_INSTRUCTION_S_ONLY_ARM(TST, ARM_NEUTRAL_S(cpu->gprs[rn], cpu->shifterOperand, aluOut), - int32_t aluOut = cpu->gprs[rn] & cpu->shifterOperand;) +DEFINE_ALU_INSTRUCTION_S_ONLY_ARM(TST, ARM_NEUTRAL_S(n, cpu->shifterOperand, aluOut), + int32_t aluOut = n & cpu->shifterOperand;) // End ALU definitions