fix: resolve timing regressions

make sure to use fetch timings when fetching instructions
This commit is contained in:
Rekai Nyangadzayi Musuka 2022-10-21 05:13:08 -03:00
parent 130d40bc7f
commit 85d4690c56
2 changed files with 25 additions and 39 deletions

View File

@ -428,22 +428,24 @@ pub const Arm7tdmi = struct {
}
pub fn step(self: *Self) void {
if (self.cpsr.t.read()) blk: {
const opcode = @truncate(u16, self.pipe.step(self, u16) orelse break :blk);
defer {
if (!self.pipe.flushed) self.r[15] += if (self.cpsr.t.read()) 2 else @as(u32, 4);
self.pipe.flushed = false;
}
if (self.cpsr.t.read()) {
const opcode = @truncate(u16, self.pipe.step(self, u16) orelse return);
if (self.logger) |*trace| trace.mgbaLog(self, opcode);
thumb.lut[thumb.idx(opcode)](self, self.bus, opcode);
} else blk: {
const opcode = self.pipe.step(self, u32) orelse break :blk;
} else {
const opcode = self.pipe.step(self, u32) orelse return;
if (self.logger) |*trace| trace.mgbaLog(self, opcode);
if (checkCond(self.cpsr, @truncate(u4, opcode >> 28))) {
arm.lut[arm.idx(opcode)](self, self.bus, opcode);
}
}
if (!self.pipe.flushed) self.r[15] += if (self.cpsr.t.read()) 2 else @as(u32, 4);
self.pipe.flushed = false;
}
pub fn stepDmaTransfer(self: *Self) bool {
@ -481,8 +483,8 @@ pub const Arm7tdmi = struct {
// Return if IME is disabled, CPSR I is set or there is nothing to handle
if (!self.bus.io.ime or self.cpsr.i.read() or should_handle == 0) return;
// If pipeline isn't full, return but reschedule the handling of the event
if (!self.pipe.isFull()) return;
// If Pipeline isn't full, we have a bug
std.debug.assert(self.pipe.isFull());
// log.debug("Handling Interrupt!", .{});
self.bus.io.haltcnt = .Execute;
@ -501,23 +503,18 @@ pub const Arm7tdmi = struct {
self.pipe.reload(self);
}
inline fn fetch(self: *Self, comptime T: type) T {
inline fn fetch(self: *Self, comptime T: type, address: u32) T {
comptime std.debug.assert(T == u32 or T == u16); // Opcode may be 32-bit (ARM) or 16-bit (THUMB)
defer self.r[15] += if (T == u32) 4 else 2;
// FIXME: You better hope this is optimized out
// Bus.read will advance the scheduler. There are different timings for CPU fetches,
// so we want to undo what Bus.read will apply. We can do this by caching the current tick
// This is very dumb.
//
// FIXME: Please rework this
const tick_cache = self.sched.tick;
defer self.sched.tick = tick_cache + Bus.fetch_timings[@boolToInt(T == u32)][@truncate(u4, self.r[15] >> 24)];
defer self.sched.tick = tick_cache + Bus.fetch_timings[@boolToInt(T == u32)][@truncate(u4, address >> 24)];
return self.bus.read(T, self.r[15]);
}
fn debug_log(self: *const Self, file: *const File, opcode: u32) void {
if (self.binary_log) {
self.skyLog(file) catch unreachable;
} else {
self.mgbaLog(file, opcode) catch unreachable;
}
return self.bus.read(T, address);
}
pub fn panic(self: *const Self, comptime format: []const u8, args: anytype) noreturn {
@ -655,15 +652,6 @@ const Pipeline = struct {
};
}
pub fn flush(self: *Self) void {
for (self.stage) |*opcode| opcode.* = null;
self.flushed = true;
// Note: If using this, add
// if (!self.pipe.flushed) self.r[15] += if (self.cpsr.t.read()) 2 else @as(u32, 4);
// to the end of Arm7tdmi.step
}
pub fn isFull(self: *const Self) bool {
return self.stage[0] != null and self.stage[1] != null;
}
@ -672,22 +660,22 @@ const Pipeline = struct {
comptime std.debug.assert(T == u32 or T == u16);
// FIXME: https://github.com/ziglang/zig/issues/12642
const opcode = self.stage[0..1][0];
var opcode = self.stage[0];
self.stage[0] = self.stage[1];
self.stage[1] = cpu.bus.read(T, cpu.r[15]);
self.stage[1] = cpu.fetch(T, cpu.r[15]);
return opcode;
}
pub fn reload(self: *Self, cpu: *Arm7tdmi) void {
if (cpu.cpsr.t.read()) {
self.stage[0] = cpu.bus.read(u16, cpu.r[15]);
self.stage[1] = cpu.bus.read(u16, cpu.r[15] + 2);
self.stage[0] = cpu.fetch(u16, cpu.r[15]);
self.stage[1] = cpu.fetch(u16, cpu.r[15] + 2);
cpu.r[15] += 4;
} else {
self.stage[0] = cpu.bus.read(u32, cpu.r[15]);
self.stage[1] = cpu.bus.read(u32, cpu.r[15] + 4);
self.stage[0] = cpu.fetch(u32, cpu.r[15]);
self.stage[1] = cpu.fetch(u32, cpu.r[15] + 4);
cpu.r[15] += 8;
}

View File

@ -73,8 +73,6 @@ pub fn fmt4(comptime op: u4) InstrFn {
cpu.cpsr.z.write(result == 0);
cpu.cpsr.c.write(overflow);
cpu.cpsr.v.write(((op1 ^ result) & (op2 ^ result)) >> 31 & 1 == 1);
// FIXME: Pretty sure CMN Is the same
},
0x6 => {
// SBC