feat(v5te): implement THUMB BLX(1), BLX(2), and ARM BLX

This commit is contained in:
2023-09-19 23:00:28 -05:00
parent 37b3fe3d10
commit 3c5d4acc5f
6 changed files with 60 additions and 39 deletions

View File

@@ -17,38 +17,37 @@ pub fn fmt16(comptime InstrFn: type, comptime cond: u4) InstrFn {
}.inner;
}
pub fn fmt18(comptime InstrFn: type) InstrFn {
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
return struct {
// B but conditional
fn inner(cpu: *Arm32, opcode: u16) void {
cpu.r[15] +%= sext(u32, u11, opcode & 0x7FF) << 1;
cpu.pipe.reload(cpu);
}
}.inner;
}
pub fn fmt19(comptime InstrFn: type, comptime is_low: bool) InstrFn {
pub fn linkExchange(comptime InstrFn: type, comptime H: u2) InstrFn {
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
return struct {
fn inner(cpu: *Arm32, opcode: u16) void {
// BL
const offset = opcode & 0x7FF;
if (is_low) {
// Instruction 2
const next_opcode = cpu.r[15] - 2;
switch (H) {
0b00 => { // Unconditional Branch
cpu.r[15] +%= sext(u32, u11, opcode & 0x7FF) << 1;
cpu.pipe.reload(cpu);
},
0b01 => { // BLX Pt. 2
if (Arm32.arch == .v4t) cpu.panic("attempted to execute THUMB BLX(1), despite ARMv4T CPU", .{});
const next_addr = cpu.r[15] - 2;
cpu.r[15] = cpu.r[14] +% (offset << 1);
cpu.r[14] = next_opcode | 1;
cpu.r[15] = (cpu.r[14] +% (offset << 1)) & ~@as(u32, 0x3);
cpu.r[14] = next_addr | 1;
cpu.cpsr.t.unset();
cpu.pipe.reload(cpu);
} else {
// Instruction 1
const lr_offset = sext(u32, u11, offset) << 12;
cpu.r[14] = (cpu.r[15] +% lr_offset) & ~@as(u32, 1);
cpu.pipe.reload(cpu);
},
0b10 => cpu.r[14] = cpu.r[15] +% (sext(u32, u11, offset) << 12), // BL / BLX Pt. 1
0b11 => { // BL Pt. 2
const next_addr = cpu.r[15] - 2;
cpu.r[15] = cpu.r[14] +% (offset << 1);
cpu.r[14] = next_addr | 1;
cpu.pipe.reload(cpu);
},
}
}
}.inner;

View File

@@ -60,6 +60,17 @@ pub fn fmt5(comptime InstrFn: type, comptime op: u2, comptime h1: u1, comptime h
const rs = @as(u4, h2) << 3 | (opcode >> 3 & 0x7);
const rd = @as(u4, h1) << 3 | (opcode & 0x7);
if (Arm32.arch == .v5te and op == 0b11 and h1 == 0b1) {
// BLX
const rm = rs;
cpu.r[14] = (cpu.r[15] - 2) | 1;
cpu.cpsr.t.write(cpu.r[rm] & 1 == 1);
cpu.r[15] = cpu.r[rm] & ~@as(u32, 1);
cpu.pipe.reload(cpu);
}
const op1 = cpu.r[rd];
const op2 = cpu.r[rs];