all repos — mgba @ 2fd9ab1197de96450c633ee56360b0606c4d478b

mGBA Game Boy Advance Emulator

Emulate division by zero edge cases (fixes #80)
Jeffrey Pfau jeffrey@endrift.com
Sat, 05 Jul 2014 05:19:58 -0700
commit

2fd9ab1197de96450c633ee56360b0606c4d478b

parent

26c33b18e17d86eaed238484f2a7db9af673d5a1

1 files changed, 34 insertions(+), 12 deletions(-)

jump to
M src/gba/gba-bios.csrc/gba/gba-bios.c

@@ -101,6 +101,38 @@ uint32_t key = cpu->memory.load32(cpu, cpu->gprs[0] + 4, 0);

cpu->gprs[0] = key / powf(2, (180.f - cpu->gprs[1] - cpu->gprs[2] / 256.f) / 12.f); } +static void _Div(struct ARMCore* cpu, int32_t num, int32_t denom) { + if (denom != 0) { + div_t result = div(num, denom); + cpu->gprs[0] = result.quot; + cpu->gprs[1] = result.rem; + cpu->gprs[3] = abs(result.quot); + } else { + switch (num) { + case 0: + cpu->gprs[0] = 1; + cpu->gprs[1] = 0; + cpu->gprs[3] = 1; + break; + case 1: + cpu->gprs[0] = 1; + cpu->gprs[1] = 1; + cpu->gprs[3] = 1; + break; + case -1: + cpu->gprs[0] = -1; + cpu->gprs[1] = -1; + cpu->gprs[3] = 1; + break; + default: + // Technically this should hang, but that would be painful to emulate in HLE + cpu->gprs[0] = 0; + cpu->gprs[1] = 0; + cpu->gprs[3] = 0; + } + } +} + void GBASwi16(struct ARMCore* cpu, int immediate) { struct GBA* gba = (struct GBA*) cpu->master; GBALog(gba, GBA_LOG_DEBUG, "SWI: %02x", immediate);

@@ -124,20 +156,10 @@ // IntrWait

ARMRaiseSWI(cpu); break; case 0x6: - { - div_t result = div(cpu->gprs[0], cpu->gprs[1]); - cpu->gprs[0] = result.quot; - cpu->gprs[1] = result.rem; - cpu->gprs[3] = abs(result.quot); - } + _Div(cpu, cpu->gprs[0], cpu->gprs[1]); break; case 0x7: - { - div_t result = div(cpu->gprs[1], cpu->gprs[0]); - cpu->gprs[0] = result.quot; - cpu->gprs[1] = result.rem; - cpu->gprs[3] = abs(result.quot); - } + _Div(cpu, cpu->gprs[1], cpu->gprs[0]); break; case 0x8: cpu->gprs[0] = sqrt(cpu->gprs[0]);