diff --git a/src/cpu.zig b/src/cpu.zig index 2828a06..dda1f7d 100644 --- a/src/cpu.zig +++ b/src/cpu.zig @@ -9,9 +9,10 @@ const Scheduler = @import("scheduler.zig").Scheduler; const Bitfield = bitfield.Bitfield; const Bit = bitfield.Bit; -const comptimeDataProcessing = @import("cpu/data_processing.zig").comptimeDataProcessing; -const comptimeSingleDataTransfer = @import("cpu/single_data_transfer.zig").comptimeSingleDataTransfer; -const comptimeHalfSignedDataTransfer = @import("cpu/half_signed_data_transfer.zig").comptimeHalfSignedDataTransfer; +const dataProcessing = @import("cpu/data_processing.zig").dataProcessing; +const singleDataTransfer = @import("cpu/single_data_transfer.zig").singleDataTransfer; +const halfAndSignedDataTransfer = @import("cpu/half_signed_data_transfer.zig").halfAndSignedDataTransfer; +const branch = @import("cpu/branch.zig").branch; pub const InstrFn = fn (*Arm7tdmi, *Bus, u32) void; const arm_lut: [0x1000]InstrFn = populate(); @@ -58,7 +59,7 @@ pub const Arm7tdmi = struct { return word; } - fn fakePC(self: *const @This()) u32 { + pub fn fakePC(self: *const @This()) u32 { return self.r[15] + 4; } @@ -128,7 +129,7 @@ fn populate() [0x1000]InstrFn { const S = i >> 4 & 1 == 1; const instrKind = i >> 5 & 0xF; - lut[i] = comptimeDataProcessing(I, S, instrKind); + lut[i] = dataProcessing(I, S, instrKind); } if (i >> 9 & 0x7 == 0b000 and i >> 3 & 1 == 1 and i & 1 == 1) { @@ -138,7 +139,7 @@ fn populate() [0x1000]InstrFn { const W = i >> 5 & 1 == 1; const L = i >> 4 & 1 == 1; - lut[i] = comptimeHalfSignedDataTransfer(P, U, I, W, L); + lut[i] = halfAndSignedDataTransfer(P, U, I, W, L); } if (i >> 10 & 0x3 == 0b01) { @@ -149,12 +150,12 @@ fn populate() [0x1000]InstrFn { const W = i >> 5 & 1 == 1; const L = i >> 4 & 1 == 1; - lut[i] = comptimeSingleDataTransfer(I, P, U, B, W, L); + lut[i] = singleDataTransfer(I, P, U, B, W, L); } if (i >> 9 & 0x7 == 0b101) { const L = i >> 8 & 1 == 1; - lut[i] = comptimeBranch(L); + lut[i] = branch(L); } } @@ -188,15 +189,3 @@ fn undefinedInstruction(_: *Arm7tdmi, _: *Bus, opcode: u32) void { const id = armIdx(opcode); std.debug.panic("[CPU] {{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 { - if (L) { - cpu.r[14] = cpu.r[15] - 4; - } - - cpu.r[15] = cpu.fakePC() +% util.u32SignExtend(24, opcode << 2); - } - }.branch; -} diff --git a/src/cpu/branch.zig b/src/cpu/branch.zig new file mode 100644 index 0000000..f421bb1 --- /dev/null +++ b/src/cpu/branch.zig @@ -0,0 +1,19 @@ +const arm = @import("../cpu.zig"); +const util = @import("../util.zig"); + +const Bus = @import("../bus.zig").Bus; + +const Arm7tdmi = arm.Arm7tdmi; +const InstrFn = arm.InstrFn; + +pub fn branch(comptime L: bool) InstrFn { + return struct { + fn inner(cpu: *Arm7tdmi, _: *Bus, opcode: u32) void { + if (L) { + cpu.r[14] = cpu.r[15] - 4; + } + + cpu.r[15] = cpu.fakePC() +% util.u32SignExtend(24, opcode << 2); + } + }.inner; +} diff --git a/src/cpu/data_processing.zig b/src/cpu/data_processing.zig index 41173ae..30866d5 100644 --- a/src/cpu/data_processing.zig +++ b/src/cpu/data_processing.zig @@ -6,9 +6,9 @@ const Bus = @import("../bus.zig").Bus; const Arm7tdmi = arm.Arm7tdmi; const InstrFn = arm.InstrFn; -pub fn comptimeDataProcessing(comptime I: bool, comptime S: bool, comptime instrKind: u4) InstrFn { +pub fn dataProcessing(comptime I: bool, comptime S: bool, comptime instrKind: u4) InstrFn { return struct { - fn dataProcessing(cpu: *Arm7tdmi, _: *Bus, opcode: u32) void { + fn inner(cpu: *Arm7tdmi, _: *Bus, opcode: u32) void { const rd = opcode >> 12 & 0xF; const op1 = opcode >> 16 & 0xF; @@ -68,5 +68,5 @@ pub fn comptimeDataProcessing(comptime I: bool, comptime S: bool, comptime instr else => std.debug.panic("[CPU] TODO: implement data processing type {}", .{instrKind}), } } - }.dataProcessing; + }.inner; } diff --git a/src/cpu/half_signed_data_transfer.zig b/src/cpu/half_signed_data_transfer.zig index 23814fc..d13f729 100644 --- a/src/cpu/half_signed_data_transfer.zig +++ b/src/cpu/half_signed_data_transfer.zig @@ -6,9 +6,9 @@ const Bus = @import("../bus.zig").Bus; const Arm7tdmi = arm.Arm7tdmi; const InstrFn = arm.InstrFn; -pub fn comptimeHalfSignedDataTransfer(comptime P: bool, comptime U: bool, comptime I: bool, comptime W: bool, comptime L: bool) InstrFn { +pub fn halfAndSignedDataTransfer(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 inner(cpu: *Arm7tdmi, bus: *Bus, opcode: u32) void { const rn = opcode >> 16 & 0xF; const rd = opcode >> 12 & 0xF; const rm = opcode & 0xF; @@ -59,5 +59,5 @@ pub fn comptimeHalfSignedDataTransfer(comptime P: bool, comptime U: bool, compti address = modified_base; if (W and P or !P) cpu.r[rn] = address; } - }.halfSignedDataTransfer; + }.inner; } diff --git a/src/cpu/single_data_transfer.zig b/src/cpu/single_data_transfer.zig index 2f9a54f..d13ca61 100644 --- a/src/cpu/single_data_transfer.zig +++ b/src/cpu/single_data_transfer.zig @@ -8,9 +8,9 @@ const Arm7tdmi = arm.Arm7tdmi; const InstrFn = arm.InstrFn; const CPSR = arm.CPSR; -pub fn comptimeSingleDataTransfer(comptime I: bool, comptime P: bool, comptime U: bool, comptime B: bool, comptime W: bool, comptime L: bool) InstrFn { +pub fn singleDataTransfer(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 inner(cpu: *Arm7tdmi, bus: *Bus, opcode: u32) void { const rn = opcode >> 16 & 0xF; const rd = opcode >> 12 & 0xF; @@ -46,7 +46,7 @@ pub fn comptimeSingleDataTransfer(comptime I: bool, comptime P: bool, comptime U // TODO: W-bit forces non-privledged mode for the transfer } - }.singleDataTransfer; + }.inner; } fn registerOffset(cpu: *Arm7tdmi, opcode: u32) u32 {