diff --git a/src/cpu.zig b/src/cpu.zig index f2d6953..ba873a7 100644 --- a/src/cpu.zig +++ b/src/cpu.zig @@ -109,14 +109,16 @@ pub const Arm7tdmi = struct { } pub inline fn hasSPSR(self: *const Self) bool { - return switch (getMode(self.cpsr.mode.read())) { + const mode = getMode(self.cpsr.mode.read()) orelse unreachable; + return switch (mode) { .System, .User => false, else => true, }; } pub inline fn isPrivileged(self: *const Self) bool { - return switch (getMode(self.cpsr.mode.read())) { + const mode = getMode(self.cpsr.mode.read()) orelse unreachable; + return switch (mode) { .User => false, else => true, }; @@ -128,11 +130,12 @@ pub const Arm7tdmi = struct { } fn changeModeFromIdx(self: *Self, next: u5) void { - self.changeMode(getMode(next)); + const mode = getMode(next) orelse unreachable; + self.changeMode(mode); } pub fn changeMode(self: *Self, next: Mode) void { - const now = getMode(self.cpsr.mode.read()); + const now = getMode(self.cpsr.mode.read()) orelse unreachable; // Bank R8 -> r12 var r: usize = 8; @@ -233,6 +236,53 @@ pub const Arm7tdmi = struct { } } + pub fn panic(self: *const Self, comptime format: []const u8, args: anytype) noreturn { + var i: usize = 0; + while (i < 16) : (i += 4) { + const i_1 = i + 1; + const i_2 = i + 2; + const i_3 = i + 3; + std.debug.print("R{}: 0x{X:0>8}\tR{}: 0x{X:0>8}\tR{}: 0x{X:0>8}\tR{}: 0x{X:0>8}\n", .{ i, self.r[i], i_1, self.r[i_1], i_2, self.r[i_2], i_3, self.r[i_3] }); + } + std.debug.print("cpsr: 0x{X:0>8} ", .{self.cpsr.raw}); + prettyPrintPsr(&self.cpsr); + + std.debug.print("spsr: 0x{X:0>8} ", .{self.spsr.raw}); + prettyPrintPsr(&self.spsr); + + std.debug.print("tick: {}\n\n", .{self.sched.tick}); + + std.debug.panic(format, args); + } + + fn prettyPrintPsr(psr: *const PSR) void { + std.debug.print("[", .{}); + + if (psr.n.read()) std.debug.print("N", .{}) else std.debug.print("-", .{}); + if (psr.z.read()) std.debug.print("Z", .{}) else std.debug.print("-", .{}); + if (psr.c.read()) std.debug.print("C", .{}) else std.debug.print("-", .{}); + if (psr.v.read()) std.debug.print("V", .{}) else std.debug.print("-", .{}); + if (psr.i.read()) std.debug.print("I", .{}) else std.debug.print("-", .{}); + if (psr.f.read()) std.debug.print("F", .{}) else std.debug.print("-", .{}); + if (psr.t.read()) std.debug.print("T", .{}) else std.debug.print("-", .{}); + std.debug.print("|", .{}); + if (getMode(psr.mode.read())) |mode| std.debug.print("{s}", .{modeString(mode)}) else std.debug.print("---", .{}); + + std.debug.print("]\n", .{}); + } + + fn modeString(mode: Mode) []const u8 { + return switch (mode) { + .User => "usr", + .Fiq => "fiq", + .Irq => "irq", + .Supervisor => "svc", + .Abort => "abt", + .Undefined => "und", + .System => "sys", + }; + } + fn skyLog(self: *const Self, file: *const File) !void { var buf: [18 * @sizeOf(u32)]u8 = undefined; @@ -533,16 +583,16 @@ const Mode = enum(u5) { System = 0b11111, }; -pub fn getMode(bits: u5) Mode { - return std.meta.intToEnum(Mode, bits) catch unreachable; +pub fn getMode(bits: u5) ?Mode { + return std.meta.intToEnum(Mode, bits) catch null; } -fn armUndefined(_: *Arm7tdmi, _: *Bus, opcode: u32) void { +fn armUndefined(cpu: *Arm7tdmi, _: *Bus, opcode: u32) void { const id = armIdx(opcode); - std.debug.panic("[CPU:ARM] ID: 0x{X:0>3} 0x{X:0>8} is an illegal opcode", .{ id, opcode }); + cpu.panic("[CPU:ARM] ID: 0x{X:0>3} 0x{X:0>8} is an illegal opcode", .{ id, opcode }); } -fn thumbUndefined(_: *Arm7tdmi, _: *Bus, opcode: u16) void { +fn thumbUndefined(cpu: *Arm7tdmi, _: *Bus, opcode: u16) void { const id = thumbIdx(opcode); - std.debug.panic("[CPU:THUMB] ID: 0b{b:0>10} 0x{X:0>2} is an illegal opcode", .{ id, opcode }); + cpu.panic("[CPU:THUMB] ID: 0b{b:0>10} 0x{X:0>2} is an illegal opcode", .{ id, opcode }); } diff --git a/src/cpu/arm/block_data_transfer.zig b/src/cpu/arm/block_data_transfer.zig index 4d400ef..82681e0 100644 --- a/src/cpu/arm/block_data_transfer.zig +++ b/src/cpu/arm/block_data_transfer.zig @@ -10,7 +10,7 @@ pub fn blockDataTransfer(comptime P: bool, comptime U: bool, comptime S: bool, c const rn = opcode >> 16 & 0xF; const base = cpu.r[rn]; - if (S and opcode >> 15 & 1 == 0) std.debug.panic("[CPU] TODO: STM/LDM with S set but R15 not in transfer list", .{}); + if (S and opcode >> 15 & 1 == 0) cpu.panic("[CPU] TODO: STM/LDM with S set but R15 not in transfer list", .{}); var address: u32 = undefined; if (U) { @@ -45,14 +45,14 @@ pub fn blockDataTransfer(comptime P: bool, comptime U: bool, comptime S: bool, c fn transfer(cpu: *Arm7tdmi, bus: *Bus, i: u5, address: u32) void { if (L) { cpu.r[i] = bus.read32(address); - if (S and i == 0xF) std.debug.panic("[CPU] TODO: SPSR_ is transferred to CPSR", .{}); + if (S and i == 0xF) cpu.panic("[CPU] TODO: SPSR_ is transferred to CPSR", .{}); } else { if (i == 0xF) { if (!S) { // TODO: Assure that this is Address of STM instruction + 12 bus.write32(address, cpu.r[i] + (12 - 4)); } else { - std.debug.panic("[CPU] TODO: STM with S set and R15 in transfer list", .{}); + cpu.panic("[CPU] TODO: STM with S set and R15 in transfer list", .{}); } } else { bus.write32(address, cpu.r[i]); diff --git a/src/cpu/arm/half_signed_data_transfer.zig b/src/cpu/arm/half_signed_data_transfer.zig index d2a725f..3986b62 100644 --- a/src/cpu/arm/half_signed_data_transfer.zig +++ b/src/cpu/arm/half_signed_data_transfer.zig @@ -47,12 +47,12 @@ pub fn halfAndSignedDataTransfer(comptime P: bool, comptime U: bool, comptime I: 0b10 => { // LDRSB cpu.r[rd] = util.u32SignExtend(8, @as(u32, bus.read8(address))); - std.debug.panic("[CPU|ARM|LDRSB] TODO: Affect the CPSR", .{}); + cpu.panic("[CPU|ARM|LDRSB] TODO: Affect the CPSR", .{}); }, 0b11 => { // LDRSH cpu.r[rd] = util.u32SignExtend(16, @as(u32, bus.read16(address))); - std.debug.panic("[CPU|ARM|LDRSH] TODO: Affect the CPSR", .{}); + cpu.panic("[CPU|ARM|LDRSH] TODO: Affect the CPSR", .{}); }, } } else { diff --git a/src/cpu/arm/psr_transfer.zig b/src/cpu/arm/psr_transfer.zig index 08f7282..f3abf07 100644 --- a/src/cpu/arm/psr_transfer.zig +++ b/src/cpu/arm/psr_transfer.zig @@ -30,7 +30,7 @@ pub fn psrTransfer(comptime I: bool, comptime R: bool, comptime kind: u2) InstrF if (cpu.isPrivileged()) cpu.setCpsr(fieldMask(&cpu.cpsr, field_mask, right)); } }, - else => std.debug.panic("[CPU/PSR Transfer] Bits 21:220 of {X:0>8} are undefined", .{opcode}), + else => cpu.panic("[CPU/PSR Transfer] Bits 21:220 of {X:0>8} are undefined", .{opcode}), } } }.inner; diff --git a/src/cpu/thumb/format1.zig b/src/cpu/thumb/format1.zig index b246163..f7fb464 100644 --- a/src/cpu/thumb/format1.zig +++ b/src/cpu/thumb/format1.zig @@ -17,7 +17,7 @@ pub fn format1(comptime op: u2, comptime offset: u5) InstrFn { 0b00 => shifter.logicalLeft(true, &cpu.cpsr, cpu.r[rs], offset), // LSL 0b01 => shifter.logicalRight(true, &cpu.cpsr, cpu.r[rs], offset), // LSR 0b10 => shifter.arithmeticRight(true, &cpu.cpsr, cpu.r[rs], offset), // ASR - else => std.debug.panic("[CPU|THUMB|Fmt1] {} is an invalid op", .{op}), + else => cpu.panic("[CPU|THUMB|Fmt1] {} is an invalid op", .{op}), }; // Equivalent to an ARM MOVS diff --git a/src/cpu/thumb/format13.zig b/src/cpu/thumb/format13.zig index 8d41155..3b32718 100644 --- a/src/cpu/thumb/format13.zig +++ b/src/cpu/thumb/format13.zig @@ -6,8 +6,8 @@ const InstrFn = @import("../../cpu.zig").ThumbInstrFn; pub fn format13(comptime _: bool) InstrFn { return struct { - fn inner(_: *Arm7tdmi, _: *Bus, _: u16) void { - std.debug.panic("[CPU|THUMB|Fmt13] Implement Format 13 THUMB Instructions", .{}); + fn inner(cpu: *Arm7tdmi, _: *Bus, _: u16) void { + cpu.panic("[CPU|THUMB|Fmt13] Implement Format 13 THUMB Instructions", .{}); } }.inner; } diff --git a/src/cpu/thumb/format16.zig b/src/cpu/thumb/format16.zig index e116818..8893ae6 100644 --- a/src/cpu/thumb/format16.zig +++ b/src/cpu/thumb/format16.zig @@ -14,7 +14,7 @@ pub fn format16(comptime cond: u4) InstrFn { const offset = u32SignExtend(8, opcode & 0xFF) << 1; const should_execute = switch (cond) { - 0xE, 0xF => std.debug.panic("[CPU/THUMB] Undefined conditional branch with condition {}", .{cond}), + 0xE, 0xF => cpu.panic("[CPU/THUMB] Undefined conditional branch with condition {}", .{cond}), else => checkCond(cpu.cpsr, cond), }; diff --git a/src/cpu/thumb/format5.zig b/src/cpu/thumb/format5.zig index 34190d4..33fb5b7 100644 --- a/src/cpu/thumb/format5.zig +++ b/src/cpu/thumb/format5.zig @@ -20,7 +20,7 @@ pub fn format5(comptime op: u2, comptime h1: u1, comptime h2: u1) InstrFn { cpu.cpsr.t.write(cpu.r[src] & 1 == 1); cpu.r[15] = cpu.r[src] & 0xFFFF_FFFE; }, - else => std.debug.panic("[CPU|THUMB|Fmt5] {} is an invalid op", .{op}), + else => cpu.panic("[CPU|THUMB|Fmt5] {} is an invalid op", .{op}), } } }.inner;