chore(v4t,v5te): don't give SWP/SWPB its own separate handler
This commit is contained in:
parent
253cbbcdff
commit
5d70e4bd1d
|
@ -38,10 +38,28 @@ pub fn halfAndSignedDataTransfer(comptime InstrFn: type, comptime P: bool, compt
|
||||||
// FIXME: I shouldn't have to use @as(u8, ...) here
|
// 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);
|
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 {
|
} else {
|
||||||
switch (op) {
|
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 => {
|
0b01 => {
|
||||||
// STRH
|
// 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, cpu.r[rd]);
|
||||||
cpu.write(u32, address + 4, cpu.r[rd + 1]);
|
cpu.write(u32, address + 4, cpu.r[rd + 1]);
|
||||||
},
|
},
|
||||||
else => unreachable,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -6,18 +6,19 @@ pub const arm = struct {
|
||||||
|
|
||||||
const processing = @import("cpu/arm/data_processing.zig").dataProcessing;
|
const processing = @import("cpu/arm/data_processing.zig").dataProcessing;
|
||||||
const transfer = @import("cpu/arm/single_data_transfer.zig").singleDataTransfer;
|
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 blockTransfer = @import("cpu/arm/block_data_transfer.zig").blockDataTransfer;
|
||||||
const branch = @import("cpu/arm/branch.zig").branch;
|
const branch = @import("cpu/arm/branch.zig").branch;
|
||||||
const branchExchange = @import("cpu/arm/branch.zig").branchAndExchange;
|
const branchExchange = @import("cpu/arm/branch.zig").branchAndExchange;
|
||||||
const swi = @import("cpu/arm/software_interrupt.zig").armSoftwareInterrupt;
|
const swi = @import("cpu/arm/software_interrupt.zig").armSoftwareInterrupt;
|
||||||
const swap = @import("cpu/arm/single_data_swap.zig").singleDataSwap;
|
|
||||||
|
|
||||||
// Control Instruction Extension Space
|
/// Load Store Instruction Extention Space
|
||||||
const control = @import("cpu/arm/psr_transfer.zig").control;
|
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
|
/// 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
|
/// Determine index into ARM InstrFn LUT
|
||||||
pub fn idx(opcode: u32) u12 {
|
pub fn idx(opcode: u32) u12 {
|
||||||
|
@ -38,33 +39,30 @@ pub const arm = struct {
|
||||||
|
|
||||||
for (&table, 0..) |*handler, i| {
|
for (&table, 0..) |*handler, i| {
|
||||||
handler.* = switch (@as(u2, i >> 10)) {
|
handler.* = switch (@as(u2, i >> 10)) {
|
||||||
0b00 => if (i == 0x121) blk: {
|
0b00 => if (i == 0x121) blk: { // 12 bits
|
||||||
break :blk branchExchange(InstrFn);
|
break :blk branchExchange(InstrFn);
|
||||||
} else if (i & 0xFBF == 0x109) blk: {
|
} else if (i & 0xF0F == 0x009) blk: { // 8 bits
|
||||||
const B = i >> 6 & 1 == 1;
|
|
||||||
break :blk swap(InstrFn, B);
|
|
||||||
} else if (i & 0xF0F == 0x009) blk: {
|
|
||||||
const L = i >> 7 & 1 == 1;
|
const L = i >> 7 & 1 == 1;
|
||||||
const U = i >> 6 & 1 == 1;
|
const U = i >> 6 & 1 == 1;
|
||||||
const A = i >> 5 & 1 == 1;
|
const A = i >> 5 & 1 == 1;
|
||||||
const S = i >> 4 & 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: {
|
} else if (i & 0xE49 == 0x009 or i & 0xE49 == 0x049) blk: { // 6 bits
|
||||||
const P = i >> 8 & 1 == 1;
|
const P = i >> 8 & 1 == 1;
|
||||||
const U = i >> 7 & 1 == 1;
|
const U = i >> 7 & 1 == 1;
|
||||||
const I = i >> 6 & 1 == 1;
|
const I = i >> 6 & 1 == 1;
|
||||||
const W = i >> 5 & 1 == 1;
|
const W = i >> 5 & 1 == 1;
|
||||||
const L = i >> 4 & 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: {
|
} else if (i & 0xD90 == 0x100) blk: { // 5 bits
|
||||||
const I = i >> 9 & 1 == 1;
|
const I = i >> 9 & 1 == 1;
|
||||||
const op = ((i >> 5) & 0x3) << 4 | (i & 0xF);
|
const op = ((i >> 5) & 0x3) << 4 | (i & 0xF);
|
||||||
break :blk control(InstrFn, I, op);
|
break :blk controlExt(InstrFn, I, op);
|
||||||
} else blk: {
|
} else blk: {
|
||||||
const I = i >> 9 & 1 == 1;
|
const I = i >> 9 & 1 == 1;
|
||||||
const S = i >> 4 & 1 == 1;
|
const S = i >> 4 & 1 == 1;
|
||||||
const instrKind = i >> 5 & 0xF;
|
const instr_kind = i >> 5 & 0xF;
|
||||||
break :blk processing(InstrFn, I, S, instrKind);
|
break :blk processing(InstrFn, I, S, instr_kind);
|
||||||
},
|
},
|
||||||
0b01 => if (i >> 9 & 1 == 1 and i & 1 == 1) und else blk: {
|
0b01 => if (i >> 9 & 1 == 1 and i & 1 == 1) und else blk: {
|
||||||
const I = i >> 9 & 1 == 1;
|
const I = i >> 9 & 1 == 1;
|
||||||
|
|
|
@ -6,18 +6,19 @@ pub const arm = struct {
|
||||||
|
|
||||||
const processing = @import("cpu/arm/data_processing.zig").dataProcessing;
|
const processing = @import("cpu/arm/data_processing.zig").dataProcessing;
|
||||||
const transfer = @import("cpu/arm/single_data_transfer.zig").singleDataTransfer;
|
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 blockTransfer = @import("cpu/arm/block_data_transfer.zig").blockDataTransfer;
|
||||||
const branch = @import("cpu/arm/branch.zig").branch;
|
const branch = @import("cpu/arm/branch.zig").branch;
|
||||||
const branchExchange = @import("cpu/arm/branch.zig").branchAndExchange;
|
const branchExchange = @import("cpu/arm/branch.zig").branchAndExchange;
|
||||||
const swi = @import("cpu/arm/software_interrupt.zig").armSoftwareInterrupt;
|
const swi = @import("cpu/arm/software_interrupt.zig").armSoftwareInterrupt;
|
||||||
const swap = @import("cpu/arm/single_data_swap.zig").singleDataSwap;
|
|
||||||
|
|
||||||
// Control Instruction Extension Space
|
/// Load Store Instruction Extention Space
|
||||||
const control = @import("cpu/arm/psr_transfer.zig").control;
|
const loadStoreExt = @import("cpu/arm/half_signed_data_transfer.zig").halfAndSignedDataTransfer;
|
||||||
|
|
||||||
// Arithmetic Instruction Extension Space
|
/// Control Instruction Extension Space
|
||||||
const multiply = @import("cpu/arm/multiply.zig").multiply;
|
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");
|
const cop = @import("cpu/arm/coprocessor.zig");
|
||||||
|
|
||||||
|
@ -42,31 +43,28 @@ pub const arm = struct {
|
||||||
handler.* = switch (@as(u2, i >> 10)) {
|
handler.* = switch (@as(u2, i >> 10)) {
|
||||||
0b00 => if (i == 0x121) blk: { // 12 bits
|
0b00 => if (i == 0x121) blk: { // 12 bits
|
||||||
break :blk branchExchange(InstrFn);
|
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
|
} else if (i & 0xF0F == 0x009) blk: { // 8 bits
|
||||||
const L = i >> 7 & 1 == 1;
|
const L = i >> 7 & 1 == 1;
|
||||||
const U = i >> 6 & 1 == 1;
|
const U = i >> 6 & 1 == 1;
|
||||||
const A = i >> 5 & 1 == 1;
|
const A = i >> 5 & 1 == 1;
|
||||||
const S = i >> 4 & 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
|
} else if (i & 0xE49 == 0x009 or i & 0xE49 == 0x049) blk: { // 6 bits
|
||||||
const P = i >> 8 & 1 == 1;
|
const P = i >> 8 & 1 == 1;
|
||||||
const U = i >> 7 & 1 == 1;
|
const U = i >> 7 & 1 == 1;
|
||||||
const I = i >> 6 & 1 == 1;
|
const I = i >> 6 & 1 == 1;
|
||||||
const W = i >> 5 & 1 == 1;
|
const W = i >> 5 & 1 == 1;
|
||||||
const L = i >> 4 & 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
|
} else if (i & 0xD90 == 0x100) blk: { // 6 bits
|
||||||
const I = i >> 9 & 1 == 1;
|
const I = i >> 9 & 1 == 1;
|
||||||
const op = ((i >> 5) & 0x3) << 4 | (i & 0xF);
|
const op = ((i >> 5) & 0x3) << 4 | (i & 0xF);
|
||||||
break :blk control(InstrFn, I, op);
|
break :blk controlExt(InstrFn, I, op);
|
||||||
} else blk: {
|
} else blk: {
|
||||||
const I = i >> 9 & 1 == 1;
|
const I = i >> 9 & 1 == 1;
|
||||||
const S = i >> 4 & 1 == 1;
|
const S = i >> 4 & 1 == 1;
|
||||||
const instrKind = i >> 5 & 0xF;
|
const instr_kind = i >> 5 & 0xF;
|
||||||
break :blk processing(InstrFn, I, S, instrKind);
|
break :blk processing(InstrFn, I, S, instr_kind);
|
||||||
},
|
},
|
||||||
0b01 => if (i >> 9 & 1 == 1 and i & 1 == 1) und else blk: {
|
0b01 => if (i >> 9 & 1 == 1 and i & 1 == 1) und else blk: {
|
||||||
const I = i >> 9 & 1 == 1;
|
const I = i >> 9 & 1 == 1;
|
||||||
|
|
Loading…
Reference in New Issue