chore: binary logging + file logging + DP chanes + fastBoot changes
This commit is contained in:
parent
90e0d9139c
commit
c4e131b92d
73
src/cpu.zig
73
src/cpu.zig
|
@ -7,6 +7,8 @@ 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 File = std.fs.File;
|
||||||
|
|
||||||
// ARM Instruction Groups
|
// ARM Instruction Groups
|
||||||
const dataProcessing = @import("cpu/arm/data_processing.zig").dataProcessing;
|
const dataProcessing = @import("cpu/arm/data_processing.zig").dataProcessing;
|
||||||
const psrTransfer = @import("cpu/arm/psr_transfer.zig").psrTransfer;
|
const psrTransfer = @import("cpu/arm/psr_transfer.zig").psrTransfer;
|
||||||
|
@ -27,6 +29,8 @@ pub const ThumbInstrFn = fn (*Arm7tdmi, *Bus, u16) void;
|
||||||
const arm_lut: [0x1000]ArmInstrFn = armPopulate();
|
const arm_lut: [0x1000]ArmInstrFn = armPopulate();
|
||||||
const thumb_lut: [0x400]ThumbInstrFn = thumbPopulate();
|
const thumb_lut: [0x400]ThumbInstrFn = thumbPopulate();
|
||||||
|
|
||||||
|
const logging_enabled: bool = true;
|
||||||
|
|
||||||
pub const Arm7tdmi = struct {
|
pub const Arm7tdmi = struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
|
@ -46,6 +50,10 @@ pub const Arm7tdmi = struct {
|
||||||
|
|
||||||
banked_spsr: [5]PSR,
|
banked_spsr: [5]PSR,
|
||||||
|
|
||||||
|
log_file: ?*const File,
|
||||||
|
log_buf: [0x100]u8,
|
||||||
|
binary_log: bool,
|
||||||
|
|
||||||
pub fn init(sched: *Scheduler, bus: *Bus) Self {
|
pub fn init(sched: *Scheduler, bus: *Bus) Self {
|
||||||
return .{
|
return .{
|
||||||
.r = [_]u32{0x00} ** 16,
|
.r = [_]u32{0x00} ** 16,
|
||||||
|
@ -56,9 +64,17 @@ 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,
|
||||||
|
.log_buf = undefined,
|
||||||
|
.binary_log = false,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn useLogger(self: *Self, file: *const File, is_binary: bool) void {
|
||||||
|
self.log_file = file;
|
||||||
|
self.binary_log = is_binary;
|
||||||
|
}
|
||||||
|
|
||||||
fn bankedIdx(mode: Mode) usize {
|
fn bankedIdx(mode: Mode) usize {
|
||||||
return switch (mode) {
|
return switch (mode) {
|
||||||
.User, .System => 0,
|
.User, .System => 0,
|
||||||
|
@ -150,8 +166,8 @@ pub const Arm7tdmi = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fastBoot(self: *Self) void {
|
pub fn fastBoot(self: *Self) void {
|
||||||
self.r[0] = 0x08000000;
|
// self.r[0] = 0x08000000;
|
||||||
self.r[1] = 0x000000EA;
|
// self.r[1] = 0x000000EA;
|
||||||
// GPRs 2 -> 12 *should* already be 0 initialized
|
// GPRs 2 -> 12 *should* already be 0 initialized
|
||||||
self.r[13] = 0x0300_7F00;
|
self.r[13] = 0x0300_7F00;
|
||||||
self.r[14] = 0x0000_0000;
|
self.r[14] = 0x0000_0000;
|
||||||
|
@ -161,18 +177,18 @@ pub const Arm7tdmi = struct {
|
||||||
self.banked_r[bankedIdx(.Irq) * 2 + 0] = 0x0300_7FA0;
|
self.banked_r[bankedIdx(.Irq) * 2 + 0] = 0x0300_7FA0;
|
||||||
self.banked_r[bankedIdx(.Supervisor) * 2 + 0] = 0x0300_7FE0;
|
self.banked_r[bankedIdx(.Supervisor) * 2 + 0] = 0x0300_7FE0;
|
||||||
|
|
||||||
self.cpsr.raw = 0x6000001F;
|
// self.cpsr.raw = 0x6000001F;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn step(self: *Self) u64 {
|
pub fn step(self: *Self) u64 {
|
||||||
if (self.cpsr.t.read()) {
|
if (self.cpsr.t.read()) {
|
||||||
const opcode = self.thumbFetch();
|
const opcode = self.thumbFetch();
|
||||||
// self.mgbaLog(@as(u32, opcode));
|
if (logging_enabled) if (self.log_file) |file| self.log(file, @as(u32, opcode));
|
||||||
|
|
||||||
thumb_lut[thumbIdx(opcode)](self, self.bus, opcode);
|
thumb_lut[thumbIdx(opcode)](self, self.bus, opcode);
|
||||||
} else {
|
} else {
|
||||||
const opcode = self.fetch();
|
const opcode = self.fetch();
|
||||||
// self.mgbaLog(opcode);
|
if (logging_enabled) if (self.log_file) |file| self.log(file, @as(u32, 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);
|
||||||
|
@ -198,10 +214,39 @@ pub const Arm7tdmi = struct {
|
||||||
return self.r[15] + 4;
|
return self.r[15] + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mgbaLog(self: *const Self, opcode: u32) void {
|
fn log(self: *const Self, file: *const File, opcode: u32) void {
|
||||||
const stderr = std.io.getStdErr().writer();
|
if (self.binary_log) {
|
||||||
std.debug.getStderrMutex().lock();
|
self.skyLog(file) catch unreachable;
|
||||||
defer std.debug.getStderrMutex().unlock();
|
} else {
|
||||||
|
self.mgbaLog(file, opcode) catch unreachable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
buf[(@sizeOf(u32) * i) + 3] = @truncate(u8, num >> 24 & 0xFF);
|
||||||
|
buf[(@sizeOf(u32) * i) + 2] = @truncate(u8, num >> 16 & 0xFF);
|
||||||
|
buf[(@sizeOf(u32) * i) + 1] = @truncate(u8, num >> 8 & 0xFF);
|
||||||
|
buf[(@sizeOf(u32) * i) + 0] = @truncate(u8, num >> 0 & 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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";
|
||||||
|
var buf: [0x100]u8 = [_]u8{0x00} ** 0x100; // this is larger than it needs to be
|
||||||
|
|
||||||
const r0 = self.r[0];
|
const r0 = self.r[0];
|
||||||
const r1 = self.r[1];
|
const r1 = self.r[1];
|
||||||
|
@ -222,8 +267,14 @@ pub const Arm7tdmi = struct {
|
||||||
|
|
||||||
const c_psr = self.cpsr.raw;
|
const c_psr = self.cpsr.raw;
|
||||||
|
|
||||||
nosuspend stderr.print("{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} | ", .{ r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, c_psr }) catch return;
|
var log_str: []u8 = undefined;
|
||||||
nosuspend if (self.cpsr.t.read()) stderr.print("{X:0>4}:\n", .{@truncate(u16, opcode)}) catch return else stderr.print("{X:0>8}:\n", .{opcode}) catch return;
|
if (self.cpsr.t.read()) {
|
||||||
|
log_str = try std.fmt.bufPrint(&buf, thumb_fmt, .{ r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, c_psr, opcode });
|
||||||
|
} else {
|
||||||
|
log_str = try std.fmt.bufPrint(&buf, arm_fmt, .{ r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, r13, r14, r15, c_psr, opcode });
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = try file.writeAll(log_str);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ pub fn dataProcessing(comptime I: bool, comptime S: bool, comptime instrKind: u4
|
||||||
// TST
|
// TST
|
||||||
if (rd == 0xF) {
|
if (rd == 0xF) {
|
||||||
undefinedTestBehaviour(cpu);
|
undefinedTestBehaviour(cpu);
|
||||||
cpu.r[15] += 4; // FIXME: This is objectively wrong I think
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ pub fn dataProcessing(comptime I: bool, comptime S: bool, comptime instrKind: u4
|
||||||
// TEQ
|
// TEQ
|
||||||
if (rd == 0xF) {
|
if (rd == 0xF) {
|
||||||
undefinedTestBehaviour(cpu);
|
undefinedTestBehaviour(cpu);
|
||||||
cpu.r[15] += 4; // FIXME: This is objectively wrong I think
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ pub fn dataProcessing(comptime I: bool, comptime S: bool, comptime instrKind: u4
|
||||||
// CMP
|
// CMP
|
||||||
if (rd == 0xF) {
|
if (rd == 0xF) {
|
||||||
undefinedTestBehaviour(cpu);
|
undefinedTestBehaviour(cpu);
|
||||||
cpu.r[15] += 4; // FIXME: This is objectively wrong I think
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ pub fn dataProcessing(comptime I: bool, comptime S: bool, comptime instrKind: u4
|
||||||
// CMN
|
// CMN
|
||||||
if (rd == 0xF) {
|
if (rd == 0xF) {
|
||||||
undefinedTestBehaviour(cpu);
|
undefinedTestBehaviour(cpu);
|
||||||
cpu.r[15] += 4; // FIXME: This is objectively wrong I think
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,4 +220,5 @@ fn testFlags(comptime S: bool, cpu: *Arm7tdmi, opcode: u32, result: u32) void {
|
||||||
fn undefinedTestBehaviour(cpu: *Arm7tdmi) void {
|
fn undefinedTestBehaviour(cpu: *Arm7tdmi) void {
|
||||||
@setCold(true);
|
@setCold(true);
|
||||||
cpu.setCpsr(cpu.spsr.raw);
|
cpu.setCpsr(cpu.spsr.raw);
|
||||||
|
cpu.r[15] += 4; // FIXME: This is objectively wrong I think
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,12 @@ pub fn main() anyerror!void {
|
||||||
var bus = try Bus.init(alloc, &scheduler, zba_args[0]);
|
var bus = try Bus.init(alloc, &scheduler, zba_args[0]);
|
||||||
defer bus.deinit();
|
defer bus.deinit();
|
||||||
|
|
||||||
|
// Support for Sky's Logs
|
||||||
|
const file = try std.fs.cwd().createFile("zba.bin", .{ .read = true });
|
||||||
|
defer file.close();
|
||||||
|
|
||||||
var cpu = Arm7tdmi.init(&scheduler, &bus);
|
var cpu = Arm7tdmi.init(&scheduler, &bus);
|
||||||
|
cpu.useLogger(&file, true);
|
||||||
cpu.fastBoot();
|
cpu.fastBoot();
|
||||||
|
|
||||||
// Initialize SDL
|
// Initialize SDL
|
||||||
|
|
Loading…
Reference in New Issue