diff --git a/src/arm/cpu/arm/half_signed_data_transfer.zig b/src/arm/cpu/arm/half_signed_data_transfer.zig index 86743ce..026ed4e 100644 --- a/src/arm/cpu/arm/half_signed_data_transfer.zig +++ b/src/arm/cpu/arm/half_signed_data_transfer.zig @@ -38,10 +38,28 @@ pub fn halfAndSignedDataTransfer(comptime InstrFn: type, comptime P: bool, compt // FIXME: I shouldn't have to use @as(u8, ...) here result = if (address & 1 == 1) sext(u32, u8, @as(u8, @truncate(value >> 8))) else sext(u32, u16, value); }, - 0b00 => unreachable, // SWP / SWPB dealt with in single_data_swap.zig + 0b00 => unreachable, } } else { switch (op) { + 0b00 => { + const B = I; + const swap_addr = cpu.r[rn]; + + if (B) { + // SWPB + const value = cpu.read(u8, swap_addr); + cpu.write(u8, swap_addr, @as(u8, @truncate(cpu.r[rm]))); + + cpu.r[rd] = value; + } else { + // SWP + const value = rotr(u32, cpu.read(u32, swap_addr), 8 * (swap_addr & 0x3)); + cpu.write(u32, swap_addr, cpu.r[rm]); + + cpu.r[rd] = value; + } + }, 0b01 => { // STRH @@ -76,7 +94,6 @@ pub fn halfAndSignedDataTransfer(comptime InstrFn: type, comptime P: bool, compt cpu.write(u32, address, cpu.r[rd]); cpu.write(u32, address + 4, cpu.r[rd + 1]); }, - else => unreachable, } } diff --git a/src/arm/cpu/arm/single_data_swap.zig b/src/arm/cpu/arm/single_data_swap.zig deleted file mode 100644 index 6604bcd..0000000 --- a/src/arm/cpu/arm/single_data_swap.zig +++ /dev/null @@ -1,29 +0,0 @@ -const rotr = @import("zba-util").rotr; - -pub fn singleDataSwap(comptime InstrFn: type, comptime B: bool) InstrFn { - const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child; - - return struct { - fn inner(cpu: *Arm32, opcode: u32) void { - const rn = opcode >> 16 & 0xF; - const rd = opcode >> 12 & 0xF; - const rm = opcode & 0xF; - - const address = cpu.r[rn]; - - if (B) { - // SWPB - const value = cpu.read(u8, address); - - // FIXME: I shouldn't have to use @as(u8, ...) here - cpu.write(u8, address, @as(u8, @truncate(cpu.r[rm]))); - cpu.r[rd] = value; - } else { - // SWP - const value = rotr(u32, cpu.read(u32, address), 8 * (address & 0x3)); - cpu.write(u32, address, cpu.r[rm]); - cpu.r[rd] = value; - } - } - }.inner; -} diff --git a/src/arm/v4t.zig b/src/arm/v4t.zig index b169730..b20d52b 100644 --- a/src/arm/v4t.zig +++ b/src/arm/v4t.zig @@ -6,18 +6,19 @@ pub const arm = struct { const processing = @import("cpu/arm/data_processing.zig").dataProcessing; const transfer = @import("cpu/arm/single_data_transfer.zig").singleDataTransfer; - const halfSignedTransfer = @import("cpu/arm/half_signed_data_transfer.zig").halfAndSignedDataTransfer; const blockTransfer = @import("cpu/arm/block_data_transfer.zig").blockDataTransfer; const branch = @import("cpu/arm/branch.zig").branch; const branchExchange = @import("cpu/arm/branch.zig").branchAndExchange; const swi = @import("cpu/arm/software_interrupt.zig").armSoftwareInterrupt; - const swap = @import("cpu/arm/single_data_swap.zig").singleDataSwap; - // Control Instruction Extension Space - const control = @import("cpu/arm/psr_transfer.zig").control; + /// Load Store Instruction Extention Space + const loadStoreExt = @import("cpu/arm/half_signed_data_transfer.zig").halfAndSignedDataTransfer; + + /// Control Instruction Extension Space + const controlExt = @import("cpu/arm/psr_transfer.zig").control; /// Arithmetic Instruction Extension Space - const multiply = @import("cpu/arm/multiply.zig").multiply; + const multiplyExt = @import("cpu/arm/multiply.zig").multiply; /// Determine index into ARM InstrFn LUT pub fn idx(opcode: u32) u12 { @@ -38,33 +39,30 @@ pub const arm = struct { for (&table, 0..) |*handler, i| { handler.* = switch (@as(u2, i >> 10)) { - 0b00 => if (i == 0x121) blk: { + 0b00 => if (i == 0x121) blk: { // 12 bits break :blk branchExchange(InstrFn); - } else if (i & 0xFBF == 0x109) blk: { - const B = i >> 6 & 1 == 1; - break :blk swap(InstrFn, B); - } else if (i & 0xF0F == 0x009) blk: { + } else if (i & 0xF0F == 0x009) blk: { // 8 bits const L = i >> 7 & 1 == 1; const U = i >> 6 & 1 == 1; const A = i >> 5 & 1 == 1; const S = i >> 4 & 1 == 1; - break :blk multiply(InstrFn, L, U, A, S); - } else if (i & 0xE49 == 0x009 or i & 0xE49 == 0x049) blk: { + break :blk multiplyExt(InstrFn, L, U, A, S); + } else if (i & 0xE49 == 0x009 or i & 0xE49 == 0x049) blk: { // 6 bits 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; - break :blk halfSignedTransfer(InstrFn, P, U, I, W, L); - } else if (i & 0xD90 == 0x100) blk: { + break :blk loadStoreExt(InstrFn, P, U, I, W, L); + } else if (i & 0xD90 == 0x100) blk: { // 5 bits const I = i >> 9 & 1 == 1; const op = ((i >> 5) & 0x3) << 4 | (i & 0xF); - break :blk control(InstrFn, I, op); + break :blk controlExt(InstrFn, I, op); } else blk: { const I = i >> 9 & 1 == 1; const S = i >> 4 & 1 == 1; - const instrKind = i >> 5 & 0xF; - break :blk processing(InstrFn, I, S, instrKind); + const instr_kind = i >> 5 & 0xF; + break :blk processing(InstrFn, I, S, instr_kind); }, 0b01 => if (i >> 9 & 1 == 1 and i & 1 == 1) und else blk: { const I = i >> 9 & 1 == 1; diff --git a/src/arm/v5te.zig b/src/arm/v5te.zig index 77393a3..7f648f3 100644 --- a/src/arm/v5te.zig +++ b/src/arm/v5te.zig @@ -6,18 +6,19 @@ pub const arm = struct { const processing = @import("cpu/arm/data_processing.zig").dataProcessing; const transfer = @import("cpu/arm/single_data_transfer.zig").singleDataTransfer; - const halfSignedTransfer = @import("cpu/arm/half_signed_data_transfer.zig").halfAndSignedDataTransfer; const blockTransfer = @import("cpu/arm/block_data_transfer.zig").blockDataTransfer; const branch = @import("cpu/arm/branch.zig").branch; const branchExchange = @import("cpu/arm/branch.zig").branchAndExchange; const swi = @import("cpu/arm/software_interrupt.zig").armSoftwareInterrupt; - const swap = @import("cpu/arm/single_data_swap.zig").singleDataSwap; - // Control Instruction Extension Space - const control = @import("cpu/arm/psr_transfer.zig").control; + /// Load Store Instruction Extention Space + const loadStoreExt = @import("cpu/arm/half_signed_data_transfer.zig").halfAndSignedDataTransfer; - // Arithmetic Instruction Extension Space - const multiply = @import("cpu/arm/multiply.zig").multiply; + /// Control Instruction Extension Space + const controlExt = @import("cpu/arm/psr_transfer.zig").control; + + /// Arithmetic Instruction Extension Space + const multiplyExt = @import("cpu/arm/multiply.zig").multiply; const cop = @import("cpu/arm/coprocessor.zig"); @@ -42,31 +43,28 @@ pub const arm = struct { handler.* = switch (@as(u2, i >> 10)) { 0b00 => if (i == 0x121) blk: { // 12 bits break :blk branchExchange(InstrFn); - } else if (i & 0xFBF == 0x109) blk: { // 11 bits - const B = i >> 6 & 1 == 1; - break :blk swap(InstrFn, B); } else if (i & 0xF0F == 0x009) blk: { // 8 bits const L = i >> 7 & 1 == 1; const U = i >> 6 & 1 == 1; const A = i >> 5 & 1 == 1; const S = i >> 4 & 1 == 1; - break :blk multiply(InstrFn, L, U, A, S); + break :blk multiplyExt(InstrFn, L, U, A, S); } else if (i & 0xE49 == 0x009 or i & 0xE49 == 0x049) blk: { // 6 bits 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; - break :blk halfSignedTransfer(InstrFn, P, U, I, W, L); + break :blk loadStoreExt(InstrFn, P, U, I, W, L); } else if (i & 0xD90 == 0x100) blk: { // 6 bits const I = i >> 9 & 1 == 1; const op = ((i >> 5) & 0x3) << 4 | (i & 0xF); - break :blk control(InstrFn, I, op); + break :blk controlExt(InstrFn, I, op); } else blk: { const I = i >> 9 & 1 == 1; const S = i >> 4 & 1 == 1; - const instrKind = i >> 5 & 0xF; - break :blk processing(InstrFn, I, S, instrKind); + const instr_kind = i >> 5 & 0xF; + break :blk processing(InstrFn, I, S, instr_kind); }, 0b01 => if (i >> 9 & 1 == 1 and i & 1 == 1) und else blk: { const I = i >> 9 & 1 == 1;