diff --git a/CHANGES b/CHANGES index 924e2889a..8410325b9 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,7 @@ Emulation fixes: - ARM: Fix STR storing PC after address calculation - ARM: Fix LDM^ writeback to user-mode register - ARM: Fix LDM^ {pc} differences (fixes mgba.io/i/1698) + - ARM: Fix edge case with Thumb SBC flags (fixes mgba.io/i/1818) - GB: Partially fix timing for skipped BIOS - GB Memory: Fix OAM DMA from top 8 kB - GB MBC: Fix MBC1 mode changing behavior diff --git a/src/arm/isa-thumb.c b/src/arm/isa-thumb.c index edd15fe2c..bae46a3bb 100644 --- a/src/arm/isa-thumb.c +++ b/src/arm/isa-thumb.c @@ -25,6 +25,13 @@ cpu->cpsr.c = ARM_BORROW_FROM(M, N, D); \ cpu->cpsr.v = ARM_V_SUBTRACTION(M, N, D); +#define THUMB_SUBTRACTION_CARRY_S(M, N, D, C) \ + cpu->cpsr.flags = 0; \ + 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 THUMB_NEUTRAL_S(M, N, D) \ cpu->cpsr.n = ARM_SIGN(D); \ cpu->cpsr.z = !(D); @@ -203,10 +210,11 @@ DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ADC, THUMB_ADDITION_S(d, n, cpu->gprs[rd]);) DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(SBC, - int n = cpu->gprs[rn] + !cpu->cpsr.c; + int n = cpu->gprs[rn]; int d = cpu->gprs[rd]; - cpu->gprs[rd] = d - n; - THUMB_SUBTRACTION_S(d, n, cpu->gprs[rd]);) + cpu->gprs[rd] = d - n - !cpu->cpsr.c; + THUMB_SUBTRACTION_CARRY_S(d, n, cpu->gprs[rd], !cpu->cpsr.c);) + DEFINE_DATA_FORM_5_INSTRUCTION_THUMB(ROR, int rs = cpu->gprs[rn] & 0xFF; if (rs) {