fix: rotate unaligned reads on BIOS open-bus
This commit is contained in:
parent
39d50466c9
commit
caaa60d1a8
|
@ -227,7 +227,7 @@ fn dbgSlowRead(self: *const Self, comptime T: type, unaligned_address: u32) T {
|
||||||
// General Internal Memory
|
// General Internal Memory
|
||||||
0x00 => blk: {
|
0x00 => blk: {
|
||||||
if (address < Bios.size)
|
if (address < Bios.size)
|
||||||
break :blk self.bios.dbgRead(T, self.cpu.r[15], address);
|
break :blk self.bios.dbgRead(T, self.cpu.r[15], unaligned_address);
|
||||||
|
|
||||||
break :blk self.openBus(T, address);
|
break :blk self.openBus(T, address);
|
||||||
},
|
},
|
||||||
|
@ -347,7 +347,7 @@ fn slowRead(self: *Self, comptime T: type, unaligned_address: u32) T {
|
||||||
// General Internal Memory
|
// General Internal Memory
|
||||||
0x00 => blk: {
|
0x00 => blk: {
|
||||||
if (address < Bios.size)
|
if (address < Bios.size)
|
||||||
break :blk self.bios.read(T, self.cpu.r[15], address);
|
break :blk self.bios.read(T, self.cpu.r[15], unaligned_address);
|
||||||
|
|
||||||
break :blk self.openBus(T, address);
|
break :blk self.openBus(T, address);
|
||||||
},
|
},
|
||||||
|
@ -437,11 +437,11 @@ inline fn rotateBy(comptime T: type, address: u32) u32 {
|
||||||
u32 => address & 3,
|
u32 => address & 3,
|
||||||
u16 => address & 1,
|
u16 => address & 1,
|
||||||
u8 => 0,
|
u8 => 0,
|
||||||
else => @compileError("Backup: Unsupported write width"),
|
else => @compileError("Unsupported write width"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn forceAlign(comptime T: type, address: u32) u32 {
|
pub inline fn forceAlign(comptime T: type, address: u32) u32 {
|
||||||
return switch (T) {
|
return switch (T) {
|
||||||
u32 => address & ~@as(u32, 3),
|
u32 => address & ~@as(u32, 3),
|
||||||
u16 => address & ~@as(u32, 1),
|
u16 => address & ~@as(u32, 1),
|
||||||
|
|
|
@ -3,6 +3,9 @@ const std = @import("std");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const log = std.log.scoped(.Bios);
|
const log = std.log.scoped(.Bios);
|
||||||
|
|
||||||
|
const rotr = @import("../../util.zig").rotr;
|
||||||
|
const forceAlign = @import("../Bus.zig").forceAlign;
|
||||||
|
|
||||||
/// Size of the BIOS in bytes
|
/// Size of the BIOS in bytes
|
||||||
pub const size = 0x4000;
|
pub const size = 0x4000;
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
@ -12,19 +15,35 @@ allocator: Allocator,
|
||||||
|
|
||||||
addr_latch: u32,
|
addr_latch: u32,
|
||||||
|
|
||||||
pub fn read(self: *Self, comptime T: type, r15: u32, addr: u32) T {
|
// https://github.com/ITotalJustice/notorious_beeg/issues/106
|
||||||
|
pub fn read(self: *Self, comptime T: type, r15: u32, address: u32) T {
|
||||||
if (r15 < Self.size) {
|
if (r15 < Self.size) {
|
||||||
|
const addr = forceAlign(T, address);
|
||||||
|
|
||||||
self.addr_latch = addr;
|
self.addr_latch = addr;
|
||||||
return self._read(T, addr);
|
return self._read(T, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("Rejected read since r15=0x{X:0>8}", .{r15});
|
log.warn("Open Bus! Read from 0x{X:0>8}, but PC was 0x{X:0>8}", .{ address, r15 });
|
||||||
return @truncate(T, self._read(T, self.addr_latch));
|
const value = self._read(u32, self.addr_latch);
|
||||||
|
|
||||||
|
return @truncate(T, rotr(u32, value, 8 * rotateBy(T, address)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dbgRead(self: *const Self, comptime T: type, r15: u32, addr: u32) T {
|
fn rotateBy(comptime T: type, address: u32) u32 {
|
||||||
if (r15 < Self.size) return self._read(T, addr);
|
return switch (T) {
|
||||||
return @truncate(T, self._read(T, self.addr_latch + 8));
|
u8 => address & 3,
|
||||||
|
u16 => address & 2,
|
||||||
|
u32 => 0,
|
||||||
|
else => @compileError("bios: unsupported read width"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dbgRead(self: *const Self, comptime T: type, r15: u32, address: u32) T {
|
||||||
|
if (r15 < Self.size) return self._read(T, forceAlign(T, address));
|
||||||
|
|
||||||
|
const value = self._read(u32, self.addr_latch);
|
||||||
|
return @truncate(T, rotr(u32, value, 8 * rotateBy(T, address)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Read without the GBA safety checks
|
/// Read without the GBA safety checks
|
||||||
|
|
Loading…
Reference in New Issue