diff --git a/src/bus.zig b/src/bus.zig index 2a41c37..c8a7400 100644 --- a/src/bus.zig +++ b/src/bus.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const GamePak = @import("pak.zig").GamePak; +const GamePak = @import("pak.zig").GamePak; const Allocator = std.mem.Allocator; pub const Bus = struct { @@ -17,11 +17,8 @@ pub const Bus = struct { } pub fn writeWord(self: *@This(), addr: u32, word: u32) void { - // TODO: Actually implement the memory mmap - if (addr >= self.pak.buf.len) { - return; - } - + // TODO: Actually implement the memory map + if (addr > self.pak.buf.len) return; self.pak.writeWord(addr, word); } @@ -30,12 +27,8 @@ pub const Bus = struct { } pub fn writeHalfWord(self: *@This(), addr: u32, halfword: u16) void { - - // TODO: Actually implement the memory mmap - if (addr >= self.pak.buf.len) { - return; - } - + // TODO: Actually implement the memory map + if (addr > self.pak.buf.len) return; self.pak.writeHalfWord(addr, halfword); } @@ -43,7 +36,9 @@ pub const Bus = struct { return self.pak.readByte(addr); } - pub fn writeByte(_: *@This(), _: u32, _: u8) void { - std.debug.panic("TODO: Implement Bus#writeByte", .{}); + pub fn writeByte(self: *@This(), addr: u32, byte: u8) void { + // TODO: Actually implement the memory map + if (addr > self.pak.buf.len) return; + self.pak.writeByte(addr, byte); } }; diff --git a/src/cpu.zig b/src/cpu.zig index 4c37c1a..c328025 100644 --- a/src/cpu.zig +++ b/src/cpu.zig @@ -7,10 +7,10 @@ const comptimeDataProcessing = @import("cpu/data_processing.zig").comptimeDataPr const comptimeSingleDataTransfer = @import("cpu/single_data_transfer.zig").comptimeSingleDataTransfer; const comptimeHalfSignedDataTransfer = @import("cpu/half_signed_data_transfer.zig").comptimeHalfSignedDataTransfer; -pub const InstrFn = fn (*ARM7TDMI, *Bus, u32) void; -const ARM_LUT: [0x1000]InstrFn = populate(); +pub const InstrFn = fn (*Arm7tdmi, *Bus, u32) void; +const arm_lut: [0x1000]InstrFn = populate(); -pub const ARM7TDMI = struct { +pub const Arm7tdmi = struct { r: [16]u32, sch: *Scheduler, bus: *Bus, @@ -27,11 +27,9 @@ pub const ARM7TDMI = struct { pub inline fn step(self: *@This()) u64 { const opcode = self.fetch(); + std.debug.print("opcode: 0x{X:}\n", .{opcode}); // Debug - std.debug.print("R15: 0x{X:}\n", .{opcode}); // Debug - - ARM_LUT[armIdx(opcode)](self, self.bus, opcode); - + arm_lut[armIdx(opcode)](self, self.bus, opcode); return 1; } @@ -52,43 +50,42 @@ fn armIdx(opcode: u32) u12 { fn populate() [0x1000]InstrFn { return comptime { - @setEvalBranchQuota(0x5000); - var lut = [_]InstrFn{undefined_instr} ** 0x1000; + @setEvalBranchQuota(0x5000); // TODO: Figure out exact size + var lut = [_]InstrFn{undefinedInstruction} ** 0x1000; var i: usize = 0; while (i < lut.len) : (i += 1) { if (i >> 10 & 0x3 == 0b00) { - const I = i >> 9 & 0x01 == 0x01; - const S = i >> 4 & 0x01 == 0x01; - const instrKind = i >> 5 & 0x0F; + const I = i >> 9 & 1 == 1; + const S = i >> 4 & 1 == 1; + const instrKind = i >> 5 & 0xF; lut[i] = comptimeDataProcessing(I, S, instrKind); } - if (i >> 9 & 0x7 == 0b000 and i >> 3 & 0x01 == 0x01 and i & 0x01 == 0x01) { - // Halfword and Signed Data Transfer with register offset - const P = i >> 8 & 0x01 == 0x01; - const U = i >> 7 & 0x01 == 0x01; - const I = i >> 6 & 0x01 == 0x01; - const W = i >> 5 & 0x01 == 0x01; - const L = i >> 4 & 0x01 == 0x01; + if (i >> 9 & 0x7 == 0b000 and i >> 3 & 1 == 1 and i & 1 == 1) { + const P = i >> 8 & 1 == 1; + const U = i >> 7 & 1 == 1; + const I = i >> 6 & 1 == 1; + const W = i >> 5 & 1 == 1; + const L = i >> 4 & 1 == 1; lut[i] = comptimeHalfSignedDataTransfer(P, U, I, W, L); } if (i >> 10 & 0x3 == 0b01) { - const I = i >> 9 & 0x01 == 0x01; - const P = i >> 8 & 0x01 == 0x01; - const U = i >> 7 & 0x01 == 0x01; - const B = i >> 6 & 0x01 == 0x01; - const W = i >> 5 & 0x01 == 0x01; - const L = i >> 4 & 0x01 == 0x01; + const I = i >> 9 & 1 == 1; + const P = i >> 8 & 1 == 1; + const U = i >> 7 & 1 == 1; + const B = i >> 6 & 1 == 1; + const W = i >> 5 & 1 == 1; + const L = i >> 4 & 1 == 1; lut[i] = comptimeSingleDataTransfer(I, P, U, B, W, L); } if (i >> 9 & 0x7 == 0b101) { - const L = i >> 8 & 0x01 == 0x01; + const L = i >> 8 & 1 == 1; lut[i] = comptimeBranch(L); } } @@ -101,70 +98,70 @@ const CPSR = struct { inner: u32, pub fn n(self: *const @This()) bool { - return self.inner >> 31 & 0x01 == 0x01; + return self.inner >> 31 & 1 == 1; } - pub fn set_n(self: *@This(), set: bool) void { - self.set_bit(31, set); + pub fn setN(self: *@This(), set: bool) void { + self.setBit(31, set); } pub fn z(self: *const @This()) bool { - return self.inner >> 30 & 0x01 == 0x01; + return self.inner >> 30 & 1 == 1; } - pub fn set_z(self: *@This(), set: bool) void { - self.set_bit(30, set); + pub fn setZ(self: *@This(), set: bool) void { + self.setBit(30, set); } pub fn c(self: *const @This()) bool { - return self.inner >> 29 & 0x01 == 0x01; + return self.inner >> 29 & 1 == 1; } - pub fn set_c(self: *@This(), set: bool) void { - self.set_bit(29, set); + pub fn setC(self: *@This(), set: bool) void { + self.setBit(29, set); } pub fn v(self: *const @This()) bool { - return self.inner >> 28 & 0x01 == 0x01; + return self.inner >> 28 & 1 == 1; } - pub fn set_v(self: *@This(), set: bool) void { - self.set_bit(28, set); + pub fn setV(self: *@This(), set: bool) void { + self.setBit(28, set); } pub fn i(self: *const @This()) bool { - return self.inner >> 7 & 0x01 == 0x01; + return self.inner >> 7 & 1 == 1; } - pub fn set_i(self: *@This(), set: bool) void { - self.set_bit(7, set); + pub fn setI(self: *@This(), set: bool) void { + self.setBit(7, set); } pub fn f(self: *const @This()) bool { - return self.inner >> 6 & 0x01 == 0x01; + return self.inner >> 6 & 1 == 1; } - pub fn set_f(self: *@This(), set: bool) void { - self.set_bit(6, set); + pub fn setF(self: *@This(), set: bool) void { + self.setBit(6, set); } pub fn t(self: *const @This()) bool { - return self.inner >> 5 & 0x01 == 0x01; + return self.inner >> 5 & 1 == 1; } - pub fn set_t(self: *@This(), set: bool) void { - self.set_bit(5, set); + pub fn setT(self: *@This(), set: bool) void { + self.setBit(5, set); } pub fn mode(self: *const @This()) Mode { return self.inner & 0x1F; } - pub fn set_mode(_: *@This(), _: Mode) void { + pub fn setMode(_: *@This(), _: Mode) void { std.debug.panic("TODO: Implement set_mode for CPSR", .{}); } - fn set_bit(self: *@This(), comptime bit: usize, set: bool) void { + fn setBit(self: *@This(), comptime bit: usize, set: bool) void { const set_val = @as(u32, @boolToInt(set)) << bit; const mask = ~(@as(u32, 1) << bit); @@ -182,14 +179,14 @@ const Mode = enum(u5) { System = 0b11111, }; -fn undefined_instr(_: *ARM7TDMI, _: *Bus, opcode: u32) void { +fn undefinedInstruction(_: *Arm7tdmi, _: *Bus, opcode: u32) void { const id = armIdx(opcode); std.debug.panic("[0x{X:}] 0x{X:} is an illegal opcode", .{ id, opcode }); } fn comptimeBranch(comptime L: bool) InstrFn { return struct { - fn branch(cpu: *ARM7TDMI, _: *Bus, opcode: u32) void { + fn branch(cpu: *Arm7tdmi, _: *Bus, opcode: u32) void { if (L) { cpu.r[14] = cpu.r[15] - 4; } diff --git a/src/cpu/data_processing.zig b/src/cpu/data_processing.zig index 07dccdf..04291dc 100644 --- a/src/cpu/data_processing.zig +++ b/src/cpu/data_processing.zig @@ -1,13 +1,13 @@ const std = @import("std"); -const cpu_mod = @import("../cpu.zig"); +const processor = @import("../cpu.zig"); const Bus = @import("../bus.zig").Bus; -const ARM7TDMI = cpu_mod.ARM7TDMI; -const InstrFn = cpu_mod.InstrFn; +const Arm7tdmi = processor.Arm7tdmi; +const InstrFn = processor.InstrFn; pub fn comptimeDataProcessing(comptime I: bool, comptime S: bool, comptime instrKind: u4) InstrFn { return struct { - fn dataProcessing(cpu: *ARM7TDMI, _: *Bus, opcode: u32) void { + fn dataProcessing(cpu: *Arm7tdmi, _: *Bus, opcode: u32) void { const rd = opcode >> 12 & 0xF; const op1 = opcode >> 16 & 0xF; @@ -15,7 +15,7 @@ pub fn comptimeDataProcessing(comptime I: bool, comptime S: bool, comptime instr if (I) { op2 = std.math.rotr(u32, opcode & 0xFF, (opcode >> 8 & 0xF) << 1); } else { - op2 = reg_op2(cpu, opcode); + op2 = registerOp2(cpu, opcode); } switch (instrKind) { @@ -34,17 +34,16 @@ pub fn comptimeDataProcessing(comptime I: bool, comptime S: bool, comptime instr 0xA => { // CMP var result: u32 = undefined; - - const op1_val = cpu.r[op1]; + + const op1_val = cpu.r[op1]; const v_ctx = (op1_val >> 31 == 0x01) or (op2 >> 31 == 0x01); - + const didOverflow = @subWithOverflow(u32, op1_val, op2, &result); - - cpu.cpsr.set_v(v_ctx and (result >> 31 & 0x01 == 0x01)); - cpu.cpsr.set_c(didOverflow); - cpu.cpsr.set_z(result == 0x00); - cpu.cpsr.set_n(result >> 31 & 0x01 == 0x01); - + + cpu.cpsr.setV(v_ctx and (result >> 31 & 0x01 == 0x01)); + cpu.cpsr.setC(didOverflow); + cpu.cpsr.setZ(result == 0x00); + cpu.cpsr.setN(result >> 31 & 0x01 == 0x01); }, else => std.debug.panic("TODO: implement data processing type {}", .{instrKind}), } @@ -52,7 +51,7 @@ pub fn comptimeDataProcessing(comptime I: bool, comptime S: bool, comptime instr }.dataProcessing; } -fn reg_op2(cpu: *const ARM7TDMI, opcode: u32) u32 { +fn registerOp2(cpu: *const Arm7tdmi, opcode: u32) u32 { var amount: u32 = undefined; if (opcode >> 4 & 0x01 == 0x01) { amount = cpu.r[opcode >> 8 & 0xF] & 0xFF; diff --git a/src/cpu/half_signed_data_transfer.zig b/src/cpu/half_signed_data_transfer.zig index 271b0b5..cd94ac2 100644 --- a/src/cpu/half_signed_data_transfer.zig +++ b/src/cpu/half_signed_data_transfer.zig @@ -1,14 +1,14 @@ const std = @import("std"); -const cpu_mod = @import("../cpu.zig"); +const processor = @import("../cpu.zig"); const util = @import("../util.zig"); const Bus = @import("../bus.zig").Bus; -const ARM7TDMI = cpu_mod.ARM7TDMI; -const InstrFn = cpu_mod.InstrFn; +const Arm7tdmi = processor.Arm7tdmi; +const InstrFn = processor.InstrFn; pub fn comptimeHalfSignedDataTransfer(comptime P: bool, comptime U: bool, comptime I: bool, comptime W: bool, comptime L: bool) InstrFn { return struct { - fn halfSignedDataTransfer(cpu: *ARM7TDMI, bus: *Bus, opcode: u32) void { + fn halfSignedDataTransfer(cpu: *Arm7tdmi, bus: *Bus, opcode: u32) void { const rn = opcode >> 16 & 0xF; const rd = opcode >> 12 & 0xF; const rm = opcode & 0xF; diff --git a/src/cpu/single_data_transfer.zig b/src/cpu/single_data_transfer.zig index 1d107dd..1cf9251 100644 --- a/src/cpu/single_data_transfer.zig +++ b/src/cpu/single_data_transfer.zig @@ -1,14 +1,14 @@ const std = @import("std"); const util = @import("../util.zig"); -const mod_cpu = @import("../cpu.zig"); +const processor = @import("../cpu.zig"); -const ARM7TDMI = mod_cpu.ARM7TDMI; -const InstrFn = mod_cpu.InstrFn; const Bus = @import("../bus.zig").Bus; +const Arm7tdmi = processor.Arm7tdmi; +const InstrFn = processor.InstrFn; pub fn comptimeSingleDataTransfer(comptime I: bool, comptime P: bool, comptime U: bool, comptime B: bool, comptime W: bool, comptime L: bool) InstrFn { return struct { - fn singleDataTransfer(cpu: *ARM7TDMI, bus: *Bus, opcode: u32) void { + fn singleDataTransfer(cpu: *Arm7tdmi, bus: *Bus, opcode: u32) void { const rn = opcode >> 16 & 0xF; const rd = opcode >> 12 & 0xF; @@ -55,7 +55,7 @@ pub fn comptimeSingleDataTransfer(comptime I: bool, comptime P: bool, comptime U }.singleDataTransfer; } -fn registerOffset(cpu: *ARM7TDMI, opcode: u32) u32 { +fn registerOffset(cpu: *Arm7tdmi, opcode: u32) u32 { const amount = opcode >> 7 & 0x1F; const rm = opcode & 0xF; const r_val = cpu.r[rm]; diff --git a/src/emu.zig b/src/emu.zig index 4c6c662..69a1696 100644 --- a/src/emu.zig +++ b/src/emu.zig @@ -1,13 +1,13 @@ const _ = @import("std"); const Scheduler = @import("scheduler.zig").Scheduler; -const ARM7TDMI = @import("cpu.zig").ARM7TDMI; +const Arm7tdmi = @import("cpu.zig").Arm7tdmi; const Bus = @import("bus.zig").Bus; -const CYCLES_PER_FRAME: u64 = 10_000; // TODO: What is this? +const cycles_per_frame: u64 = 10_000; // TODO: How many cycles actually? -pub fn runFrame(sch: *Scheduler, cpu: *ARM7TDMI, bus: *Bus) void { - const frame_end = sch.tick + CYCLES_PER_FRAME; +pub fn runFrame(sch: *Scheduler, cpu: *Arm7tdmi, bus: *Bus) void { + const frame_end = sch.tick + cycles_per_frame; while (sch.tick < frame_end) { while (sch.tick < sch.nextTimestamp()) { diff --git a/src/main.zig b/src/main.zig index 55e0684..2a07800 100644 --- a/src/main.zig +++ b/src/main.zig @@ -1,10 +1,9 @@ const std = @import("std"); +const emu = @import("emu.zig"); const Scheduler = @import("scheduler.zig").Scheduler; const Bus = @import("bus.zig").Bus; -const ARM7TDMI = @import("cpu.zig").ARM7TDMI; - -const emu = @import("emu.zig"); +const Arm7tdmi = @import("cpu.zig").Arm7tdmi; pub fn main() anyerror!void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; @@ -13,7 +12,7 @@ pub fn main() anyerror!void { var bus = try Bus.withPak(alloc, "./bin/demo/beeg/beeg.gba"); var scheduler = Scheduler.new(alloc); - var cpu = ARM7TDMI.new(&scheduler, &bus); + var cpu = Arm7tdmi.new(&scheduler, &bus); while (true) { emu.runFrame(&scheduler, &cpu, &bus); diff --git a/src/pak.zig b/src/pak.zig index f16ca3c..dafba49 100644 --- a/src/pak.zig +++ b/src/pak.zig @@ -39,4 +39,8 @@ pub const GamePak = struct { pub fn readByte(self: *const @This(), addr: u32) u8 { return self.buf[addr]; } + + pub fn writeByte(self: *@This(), addr: u32, byte: u8) void { + self.buf[addr] = byte; + } }; diff --git a/src/scheduler.zig b/src/scheduler.zig index a14c013..760d856 100644 --- a/src/scheduler.zig +++ b/src/scheduler.zig @@ -1,7 +1,7 @@ const std = @import("std"); -const ARM7TDMI = @import("cpu.zig").ARM7TDMI; -const Bus = @import("bus.zig").Bus; +const Bus = @import("bus.zig").Bus; +const Arm7tdmi = @import("cpu.zig").Arm7tdmi; const Order = std.math.Order; const PriorityQueue = std.PriorityQueue; const Allocator = std.mem.Allocator; @@ -21,7 +21,7 @@ pub const Scheduler = struct { return scheduler; } - pub fn handleEvent(self: *@This(), _: *ARM7TDMI, _: *Bus) void { + pub fn handleEvent(self: *@This(), _: *Arm7tdmi, _: *Bus) void { const should_handle = if (self.queue.peek()) |e| self.tick >= e.tick else false; if (should_handle) { @@ -47,8 +47,7 @@ pub const Event = struct { tick: u64, }; -fn lessThan(context: void, a: Event, b: Event) Order { - _ = context; +fn lessThan(_: void, a: Event, b: Event) Order { return std.math.order(a.tick, b.tick); }