From 67a785cc2261203935387e61759bb863442440dc Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Fri, 21 Oct 2022 05:12:18 -0300 Subject: [PATCH] fix(cpu): force align thumb and arm block data transfers --- src/cpu/arm/block_data_transfer.zig | 18 ++++---- src/cpu/thumb/block_data_transfer.zig | 64 +++++++++++++-------------- 2 files changed, 40 insertions(+), 42 deletions(-) diff --git a/src/cpu/arm/block_data_transfer.zig b/src/cpu/arm/block_data_transfer.zig index f72e9b0..892eeeb 100644 --- a/src/cpu/arm/block_data_transfer.zig +++ b/src/cpu/arm/block_data_transfer.zig @@ -48,17 +48,17 @@ pub fn blockDataTransfer(comptime P: bool, comptime U: bool, comptime S: bool, c var address = start; if (rlist == 0) { - var pc_addr = cpu.r[rn]; + var und_addr = cpu.r[rn]; if (U) { - pc_addr += if (P) 4 else 0; + und_addr += if (P) 4 else 0; } else { - pc_addr -= 0x40 - if (!P) 4 else 0; + und_addr -= 0x40 - if (!P) 4 else 0; } if (L) { - cpu.r[15] = bus.read32(pc_addr); + cpu.r[15] = bus.read32(und_addr & 0xFFFF_FFFC); } else { - bus.write32(pc_addr, cpu.r[15] + 8); + bus.write32(und_addr & 0xFFFF_FFFC, cpu.r[15] + 8); } cpu.r[rn] = if (U) cpu.r[rn] + 0x40 else cpu.r[rn] - 0x40; @@ -85,9 +85,9 @@ pub fn blockDataTransfer(comptime P: bool, comptime U: bool, comptime S: bool, c if (L) { if (S and !r15_present) { // Always Transfer User mode Registers - cpu.setUserModeRegister(i, bus.read32(address)); + cpu.setUserModeRegister(i, bus.read32(address & 0xFFFF_FFFC)); } else { - const value = bus.read32(address); + const value = bus.read32(address & 0xFFFF_FFFC); cpu.r[i] = if (i == 0xF) value & 0xFFFF_FFFC else value; if (S and i == 0xF) cpu.setCpsr(cpu.spsr.raw); } @@ -96,9 +96,9 @@ pub fn blockDataTransfer(comptime P: bool, comptime U: bool, comptime S: bool, c // Always Transfer User mode Registers // This happens regardless if r15 is in the list const value = cpu.getUserModeRegister(i); - bus.write32(address, value + if (i == 0xF) 8 else @as(u32, 0)); // PC is already 4 ahead to make 12 + bus.write32(address & 0xFFFF_FFFC, value + if (i == 0xF) 8 else @as(u32, 0)); // PC is already 4 ahead to make 12 } else { - bus.write32(address, cpu.r[i] + if (i == 0xF) 8 else @as(u32, 0)); + bus.write32(address & 0xFFFF_FFFC, cpu.r[i] + if (i == 0xF) 8 else @as(u32, 0)); } } } diff --git a/src/cpu/thumb/block_data_transfer.zig b/src/cpu/thumb/block_data_transfer.zig index 098d344..975623d 100644 --- a/src/cpu/thumb/block_data_transfer.zig +++ b/src/cpu/thumb/block_data_transfer.zig @@ -5,44 +5,42 @@ const InstrFn = @import("../../cpu.zig").ThumbInstrFn; pub fn format14(comptime L: bool, comptime R: bool) InstrFn { return struct { fn inner(cpu: *Arm7tdmi, bus: *Bus, opcode: u16) void { - var address: u32 = undefined; + const count = countRlist(opcode); + const start = cpu.r[13] - if (!L) 4 * (@boolToInt(R) + count) else 0; + + var end = cpu.r[13]; if (L) { - // POP - address = cpu.r[13]; - - var i: u4 = 0; - while (i < 8) : (i += 1) { - if ((opcode >> i) & 1 == 1) { - cpu.r[i] = bus.read32(address); - address += 4; - } - } - - if (R) { - const value = bus.read32(address); - cpu.r[15] = value & 0xFFFF_FFFE; - address += 4; - } + end += 4 * (@boolToInt(R) + count); } else { - address = cpu.r[13] - 4; + end -= 4; + } - if (R) { - bus.write32(address, cpu.r[14]); - address -= 4; - } + var address = start; - var i: u4 = 8; - while (i > 0) : (i -= 1) { - const j = i - 1; - - if ((opcode >> j) & 1 == 1) { - bus.write32(address, cpu.r[j]); - address -= 4; + var i: u4 = 0; + while (i < 8) : (i += 1) { + if (opcode >> i & 1 == 1) { + if (L) { + cpu.r[i] = bus.read32(address & 0xFFFF_FFFC); + } else { + bus.write32(address & 0xFFFF_FFFC, cpu.r[i]); } + + address += 4; } } - cpu.r[13] = address + if (!L) 4 else 0; + if (R) { + if (L) { + const value = bus.read32(address & 0xFFFF_FFFC); + cpu.r[15] = value & 0xFFFF_FFFE; + } else { + bus.write32(address & 0xFFFF_FFFC, cpu.r[14]); + } + address += 4; + } + + cpu.r[13] = if (L) end else cpu.r[13] - 4 * (@boolToInt(R) + count); } }.inner; } @@ -54,7 +52,7 @@ pub fn format15(comptime L: bool, comptime rb: u3) InstrFn { const end_address = cpu.r[rb] + 4 * countRlist(opcode); if (opcode & 0xFF == 0) { - if (L) cpu.r[15] = bus.read32(address) else bus.write32(address, cpu.r[15] + 4); + if (L) cpu.r[15] = bus.read32(address & 0xFFFF_FFFC) else bus.write32(address & 0xFFFF_FFFC, cpu.r[15] + 4); cpu.r[rb] += 0x40; return; } @@ -65,9 +63,9 @@ pub fn format15(comptime L: bool, comptime rb: u3) InstrFn { while (i < 8) : (i += 1) { if (opcode >> i & 1 == 1) { if (L) { - cpu.r[i] = bus.read32(address); + cpu.r[i] = bus.read32(address & 0xFFFF_FFFC); } else { - bus.write32(address, cpu.r[i]); + bus.write32(address & 0xFFFF_FFFC, cpu.r[i]); } if (!L and first_write) {