fix(v5te): rework MSR/MRS handling to account for v5TE extension space

This commit is contained in:
Rekai Nyangadzayi Musuka 2023-09-07 01:23:58 -05:00
parent 6dde25bd0f
commit 177f9b55a9
3 changed files with 52 additions and 39 deletions

View File

@ -1,29 +1,42 @@
const std = @import("std"); const std = @import("std");
const rotr = @import("zba-util").rotr;
const PSR = @import("../../../arm.zig").PSR; const PSR = @import("../../../arm.zig").PSR;
const log = std.log.scoped(.PsrTransfer); const log = std.log.scoped(.ctrl_ext_space);
const rotr = @import("zba-util").rotr; pub fn control(comptime InstrFn: type, comptime I: bool, comptime op: u6) InstrFn {
pub fn psrTransfer(comptime InstrFn: type, comptime I: bool, comptime R: bool, comptime kind: u2) InstrFn {
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child; const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
return struct { return struct {
fn inner(cpu: *Arm32, opcode: u32) void { fn inner(cpu: *Arm32, opcode: u32) void {
switch (kind) { if (I) {
0b00 => { // MSR (register)
// MRS const R = op >> 5 & 1 == 1;
msr(R, I, cpu, opcode);
return;
}
switch (op) {
0b00_0000, 0b10_0000 => { // MRS
const R = op >> 5 & 1 == 1;
const rd = opcode >> 12 & 0xF; const rd = opcode >> 12 & 0xF;
if (R and !cpu.hasSPSR()) log.err("Tried to read SPSR from User/System Mode", .{}); if (R and !cpu.hasSPSR()) log.err("Tried to read SPSR from User/System Mode", .{});
cpu.r[rd] = if (R) cpu.spsr.raw else cpu.cpsr.raw; cpu.r[rd] = if (R) cpu.spsr.raw else cpu.cpsr.raw;
}, },
0b10 => { 0b01_0000, 0b11_0000 => { // MSR (register)
// MSR const R = op >> 5 & 1 == 1;
msr(R, false, cpu, opcode);
},
else => cpu.panic("unhandled instruction: 0x{X:0>8}", .{opcode}),
}
}
inline fn msr(comptime R: bool, comptime imm: bool, cpu: *Arm32, opcode: u32) void {
const field_mask: u4 = @truncate(opcode >> 16 & 0xF); const field_mask: u4 = @truncate(opcode >> 16 & 0xF);
const rm_idx = opcode & 0xF; const rm_idx = opcode & 0xF;
const right = if (I) rotr(u32, opcode & 0xFF, (opcode >> 8 & 0xF) * 2) else cpu.r[rm_idx]; const right = if (imm) rotr(u32, opcode & 0xFF, (opcode >> 8 & 0xF) * 2) else cpu.r[rm_idx];
if (R and !cpu.hasSPSR()) log.err("Tried to write to SPSR in User/System Mode", .{}); if (R and !cpu.hasSPSR()) log.err("Tried to write to SPSR in User/System Mode", .{});
@ -35,9 +48,6 @@ pub fn psrTransfer(comptime InstrFn: type, comptime I: bool, comptime R: bool, c
} else { } else {
if (cpu.isPrivileged()) cpu.setCpsr(fieldMask(&cpu.cpsr, field_mask, right)); if (cpu.isPrivileged()) cpu.setCpsr(fieldMask(&cpu.cpsr, field_mask, right));
} }
},
else => cpu.panic("[CPU/PSR Transfer] Bits 21:220 of {X:0>8} are undefined", .{opcode}),
}
} }
}.inner; }.inner;
} }

View File

@ -5,7 +5,6 @@ pub const arm = struct {
pub const lut: [0x1000]InstrFn = populate(); pub const lut: [0x1000]InstrFn = populate();
const processing = @import("cpu/arm/data_processing.zig").dataProcessing; const processing = @import("cpu/arm/data_processing.zig").dataProcessing;
const psrTransfer = @import("cpu/arm/psr_transfer.zig").psrTransfer;
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 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;
@ -14,6 +13,9 @@ pub const arm = struct {
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; const swap = @import("cpu/arm/single_data_swap.zig").singleDataSwap;
// Control Instruction Extension Space
const control = @import("cpu/arm/psr_transfer.zig").control;
/// Arithmetic Instruction Extension Space /// Arithmetic Instruction Extension Space
const multiply = @import("cpu/arm/multiply.zig").multiply; const multiply = @import("cpu/arm/multiply.zig").multiply;
@ -56,9 +58,9 @@ pub const arm = struct {
break :blk halfSignedTransfer(InstrFn, P, U, I, W, L); break :blk halfSignedTransfer(InstrFn, P, U, I, W, L);
} else if (i & 0xD90 == 0x100) blk: { } else if (i & 0xD90 == 0x100) blk: {
const I = i >> 9 & 1 == 1; const I = i >> 9 & 1 == 1;
const R = i >> 6 & 1 == 1; const op = ((i >> 5) & 0x3) << 4 | (i & 0xF);
const kind = i >> 4 & 0x3;
break :blk psrTransfer(InstrFn, I, R, kind); break :blk control(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;

View File

@ -5,7 +5,6 @@ pub const arm = struct {
pub const lut: [0x1000]InstrFn = populate(); pub const lut: [0x1000]InstrFn = populate();
const processing = @import("cpu/arm/data_processing.zig").dataProcessing; const processing = @import("cpu/arm/data_processing.zig").dataProcessing;
const psrTransfer = @import("cpu/arm/psr_transfer.zig").psrTransfer;
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 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;
@ -14,6 +13,9 @@ pub const arm = struct {
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; const swap = @import("cpu/arm/single_data_swap.zig").singleDataSwap;
// Control Instruction Extension Space
const control = @import("cpu/arm/psr_transfer.zig").control;
// Arithmetic Instruction Extension Space // Arithmetic Instruction Extension Space
const multiply = @import("cpu/arm/multiply.zig").multiply; const multiply = @import("cpu/arm/multiply.zig").multiply;
@ -39,31 +41,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 == 0x161) blk: { } else if (i == 0x161) blk: { // 12 bits
break :blk clz(InstrFn); break :blk clz(InstrFn);
} else if (i & 0xFBF == 0x109) blk: { } else if (i & 0xFBF == 0x109) blk: { // 11 bits
const B = i >> 6 & 1 == 1; const B = i >> 6 & 1 == 1;
break :blk swap(InstrFn, B); 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 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 multiply(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 halfSignedTransfer(InstrFn, P, U, I, W, L);
} else if (i & 0xD90 == 0x100) blk: { } else if (i & 0xD90 == 0x100) blk: { // 6 bits
const I = i >> 9 & 1 == 1; const I = i >> 9 & 1 == 1;
const R = i >> 6 & 1 == 1; const op = ((i >> 5) & 0x3) << 4 | (i & 0xF);
const kind = i >> 4 & 0x3; break :blk control(InstrFn, I, op);
break :blk psrTransfer(InstrFn, I, R, kind);
} 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;