feat: reimplement cpu logging
This commit is contained in:
parent
53eec5c3ff
commit
2c8616f610
|
@ -6,6 +6,7 @@ const Bit = @import("bitfield").Bit;
|
||||||
const Bitfield = @import("bitfield").Bitfield;
|
const Bitfield = @import("bitfield").Bitfield;
|
||||||
const Scheduler = @import("scheduler.zig").Scheduler;
|
const Scheduler = @import("scheduler.zig").Scheduler;
|
||||||
const FilePaths = @import("util.zig").FilePaths;
|
const FilePaths = @import("util.zig").FilePaths;
|
||||||
|
const Logger = @import("util.zig").Logger;
|
||||||
|
|
||||||
const File = std.fs.File;
|
const File = std.fs.File;
|
||||||
|
|
||||||
|
@ -225,7 +226,7 @@ pub const thumb = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const enable_logging = false;
|
const cpu_logging = @import("emu.zig").cpu_logging;
|
||||||
const log = std.log.scoped(.Arm7Tdmi);
|
const log = std.log.scoped(.Arm7Tdmi);
|
||||||
|
|
||||||
pub const Arm7tdmi = struct {
|
pub const Arm7tdmi = struct {
|
||||||
|
@ -247,9 +248,7 @@ pub const Arm7tdmi = struct {
|
||||||
|
|
||||||
banked_spsr: [5]PSR,
|
banked_spsr: [5]PSR,
|
||||||
|
|
||||||
log_file: ?*const File,
|
logger: ?Logger,
|
||||||
log_buf: [0x100]u8,
|
|
||||||
binary_log: bool,
|
|
||||||
|
|
||||||
pub fn init(sched: *Scheduler, bus: *Bus) Self {
|
pub fn init(sched: *Scheduler, bus: *Bus) Self {
|
||||||
return Self{
|
return Self{
|
||||||
|
@ -261,15 +260,12 @@ pub const Arm7tdmi = struct {
|
||||||
.banked_fiq = [_]u32{0x00} ** 10,
|
.banked_fiq = [_]u32{0x00} ** 10,
|
||||||
.banked_r = [_]u32{0x00} ** 12,
|
.banked_r = [_]u32{0x00} ** 12,
|
||||||
.banked_spsr = [_]PSR{.{ .raw = 0x0000_0000 }} ** 5,
|
.banked_spsr = [_]PSR{.{ .raw = 0x0000_0000 }} ** 5,
|
||||||
.log_file = null,
|
.logger = null,
|
||||||
.log_buf = undefined,
|
|
||||||
.binary_log = false,
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn useLogger(self: *Self, file: *const File, is_binary: bool) void {
|
pub fn attach(self: *Self, log_file: std.fs.File) void {
|
||||||
self.log_file = file;
|
self.logger = Logger.init(log_file);
|
||||||
self.binary_log = is_binary;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fn bankedIdx(mode: Mode, kind: BankedKind) usize {
|
inline fn bankedIdx(mode: Mode, kind: BankedKind) usize {
|
||||||
|
@ -426,12 +422,12 @@ pub const Arm7tdmi = struct {
|
||||||
pub fn step(self: *Self) void {
|
pub fn step(self: *Self) void {
|
||||||
if (self.cpsr.t.read()) {
|
if (self.cpsr.t.read()) {
|
||||||
const opcode = self.fetch(u16);
|
const opcode = self.fetch(u16);
|
||||||
if (enable_logging) if (self.log_file) |file| self.debug_log(file, opcode);
|
if (cpu_logging) self.logger.?.mgbaLog(self, opcode);
|
||||||
|
|
||||||
thumb.lut[thumbIdx(opcode)](self, self.bus, opcode);
|
thumb.lut[thumbIdx(opcode)](self, self.bus, opcode);
|
||||||
} else {
|
} else {
|
||||||
const opcode = self.fetch(u32);
|
const opcode = self.fetch(u32);
|
||||||
if (enable_logging) if (self.log_file) |file| self.debug_log(file, opcode);
|
if (cpu_logging) self.logger.?.mgbaLog(self, opcode);
|
||||||
|
|
||||||
if (checkCond(self.cpsr, @truncate(u4, opcode >> 28))) {
|
if (checkCond(self.cpsr, @truncate(u4, opcode >> 28))) {
|
||||||
arm.lut[armIdx(opcode)](self, self.bus, opcode);
|
arm.lut[armIdx(opcode)](self, self.bus, opcode);
|
||||||
|
@ -509,14 +505,6 @@ pub const Arm7tdmi = struct {
|
||||||
return self.r[15] + 4;
|
return self.r[15] + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn panic(self: *const Self, comptime format: []const u8, args: anytype) noreturn {
|
pub fn panic(self: *const Self, comptime format: []const u8, args: anytype) noreturn {
|
||||||
var i: usize = 0;
|
var i: usize = 0;
|
||||||
while (i < 16) : (i += 4) {
|
while (i < 16) : (i += 4) {
|
||||||
|
@ -574,25 +562,6 @@ pub const Arm7tdmi = struct {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn skyLog(self: *const Self, file: *const File) !void {
|
|
||||||
var buf: [18 * @sizeOf(u32)]u8 = undefined;
|
|
||||||
|
|
||||||
// Write Registers
|
|
||||||
var i: usize = 0;
|
|
||||||
while (i < 0x10) : (i += 1) {
|
|
||||||
skyWrite(&buf, i, self.r[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
skyWrite(&buf, 0x10, self.cpsr.raw);
|
|
||||||
skyWrite(&buf, 0x11, if (self.hasSPSR()) self.spsr.raw else self.cpsr.raw);
|
|
||||||
_ = try file.writeAll(&buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn skyWrite(buf: []u8, i: usize, num: u32) void {
|
|
||||||
const j = @sizeOf(u32) * i;
|
|
||||||
std.mem.writeIntSliceNative(u32, buf[j..(j + @sizeOf(u32))], num);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mgbaLog(self: *const Self, file: *const File, opcode: u32) !void {
|
fn mgbaLog(self: *const Self, file: *const File, opcode: u32) !void {
|
||||||
const thumb_fmt = "{X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} cpsr: {X:0>8} | {X:0>4}:\n";
|
const thumb_fmt = "{X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} cpsr: {X:0>8} | {X:0>4}:\n";
|
||||||
const arm_fmt = "{X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} cpsr: {X:0>8} | {X:0>8}:\n";
|
const arm_fmt = "{X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} cpsr: {X:0>8} | {X:0>8}:\n";
|
||||||
|
|
|
@ -14,6 +14,7 @@ const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
const sync_audio = false;
|
const sync_audio = false;
|
||||||
const sync_video: RunKind = .UnlimitedFPS;
|
const sync_video: RunKind = .UnlimitedFPS;
|
||||||
|
pub const cpu_logging = false;
|
||||||
|
|
||||||
// 228 Lines which consist of 308 dots (which are 4 cycles long)
|
// 228 Lines which consist of 308 dots (which are 4 cycles long)
|
||||||
const cycles_per_frame: u64 = 228 * (308 * 4); //280896
|
const cycles_per_frame: u64 = 228 * (308 * 4); //280896
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const Log2Int = std.math.Log2Int;
|
const Log2Int = std.math.Log2Int;
|
||||||
|
const Arm7tdmi = @import("cpu.zig").Arm7tdmi;
|
||||||
|
|
||||||
// Sign-Extend value of type `T` to type `U`
|
// Sign-Extend value of type `T` to type `U`
|
||||||
pub fn sext(comptime T: type, comptime U: type, value: T) T {
|
pub fn sext(comptime T: type, comptime U: type, value: T) T {
|
||||||
|
@ -112,3 +113,64 @@ pub fn writeUndefined(log: anytype, comptime format: []const u8, args: anytype)
|
||||||
log.warn(format, args);
|
log.warn(format, args);
|
||||||
if (builtin.mode == .Debug) std.debug.panic("TODO: Implement I/O Register", .{});
|
if (builtin.mode == .Debug) std.debug.panic("TODO: Implement I/O Register", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const Logger = struct {
|
||||||
|
const Self = @This();
|
||||||
|
|
||||||
|
buf: std.io.BufferedWriter(4096 << 2, std.fs.File.Writer),
|
||||||
|
|
||||||
|
pub fn init(file: std.fs.File) Self {
|
||||||
|
return .{
|
||||||
|
.buf = .{ .unbuffered_writer = file.writer() },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print(self: *Self, comptime format: []const u8, args: anytype) !void {
|
||||||
|
try self.buf.writer().print(format, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mgbaLog(self: *Self, arm7tdmi: *const Arm7tdmi, opcode: u32) void {
|
||||||
|
const fmt_base = "{X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} {X:0>8} cpsr: {X:0>8} | ";
|
||||||
|
const thumb_fmt = fmt_base ++ "{X:0>4}:\n";
|
||||||
|
const arm_fmt = fmt_base ++ "{X:0>8}:\n";
|
||||||
|
|
||||||
|
if (arm7tdmi.cpsr.t.read()) {
|
||||||
|
if (opcode >> 11 == 0x1E) {
|
||||||
|
// Instruction 1 of a BL Opcode, print in ARM mode
|
||||||
|
const low = arm7tdmi.bus.debugRead(u16, arm7tdmi.r[15]);
|
||||||
|
const bl_opcode = @as(u32, opcode) << 16 | low;
|
||||||
|
|
||||||
|
self.print(arm_fmt, Self.fmtArgs(arm7tdmi, bl_opcode)) catch @panic("failed to write to log file");
|
||||||
|
} else {
|
||||||
|
self.print(thumb_fmt, Self.fmtArgs(arm7tdmi, opcode)) catch @panic("failed to write to log file");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.print(arm_fmt, Self.fmtArgs(arm7tdmi, opcode)) catch @panic("failed to write to log file");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fmtArgs(arm7tdmi: *const Arm7tdmi, opcode: u32) FmtArgTuple {
|
||||||
|
return .{
|
||||||
|
arm7tdmi.r[0],
|
||||||
|
arm7tdmi.r[1],
|
||||||
|
arm7tdmi.r[2],
|
||||||
|
arm7tdmi.r[3],
|
||||||
|
arm7tdmi.r[4],
|
||||||
|
arm7tdmi.r[5],
|
||||||
|
arm7tdmi.r[6],
|
||||||
|
arm7tdmi.r[7],
|
||||||
|
arm7tdmi.r[8],
|
||||||
|
arm7tdmi.r[9],
|
||||||
|
arm7tdmi.r[10],
|
||||||
|
arm7tdmi.r[11],
|
||||||
|
arm7tdmi.r[12],
|
||||||
|
arm7tdmi.r[13],
|
||||||
|
arm7tdmi.r[14],
|
||||||
|
arm7tdmi.r[15],
|
||||||
|
arm7tdmi.cpsr.raw,
|
||||||
|
opcode,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const FmtArgTuple = std.meta.Tuple(&.{ u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32, u32 });
|
||||||
|
|
|
@ -14,6 +14,7 @@ const Allocator = std.mem.Allocator;
|
||||||
const log = std.log.scoped(.CLI);
|
const log = std.log.scoped(.CLI);
|
||||||
const width = @import("core/ppu.zig").width;
|
const width = @import("core/ppu.zig").width;
|
||||||
const height = @import("core/ppu.zig").height;
|
const height = @import("core/ppu.zig").height;
|
||||||
|
const arm7tdmi_logging = @import("core/emu.zig").cpu_logging;
|
||||||
pub const log_level = if (builtin.mode != .Debug) .info else std.log.default_level;
|
pub const log_level = if (builtin.mode != .Debug) .info else std.log.default_level;
|
||||||
|
|
||||||
// TODO: Reimpl Logging
|
// TODO: Reimpl Logging
|
||||||
|
@ -48,6 +49,10 @@ pub fn main() anyerror!void {
|
||||||
|
|
||||||
var arm7tdmi = Arm7tdmi.init(&scheduler, &bus);
|
var arm7tdmi = Arm7tdmi.init(&scheduler, &bus);
|
||||||
|
|
||||||
|
const log_file: ?std.fs.File = if (arm7tdmi_logging) try std.fs.cwd().createFile("zba.log", .{}) else null;
|
||||||
|
defer if (log_file) |file| file.close();
|
||||||
|
|
||||||
|
if (log_file) |file| arm7tdmi.attach(file);
|
||||||
bus.attach(&arm7tdmi); // TODO: Shrink Surface (only CPSR and r15?)
|
bus.attach(&arm7tdmi); // TODO: Shrink Surface (only CPSR and r15?)
|
||||||
if (paths.bios == null) arm7tdmi.fastBoot();
|
if (paths.bios == null) arm7tdmi.fastBoot();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue