feat: reimplement cpu logging

This commit is contained in:
Rekai Nyangadzayi Musuka 2022-07-27 14:49:55 -03:00
parent 53eec5c3ff
commit 2c8616f610
4 changed files with 76 additions and 39 deletions

View File

@ -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";

View File

@ -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

View File

@ -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 });

View File

@ -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();