chore: progress towards working pipeline

focus on THMB branching and a little bit of ARM data processing
This commit is contained in:
Rekai Nyangadzayi Musuka 2022-07-02 04:45:34 -03:00
parent d279c4c519
commit 45f65ce877
6 changed files with 23 additions and 32 deletions

View File

@ -11,8 +11,7 @@ pub fn branch(comptime L: bool) InstrFn {
fn inner(cpu: *Arm7tdmi, _: *Bus, opcode: u32) void {
if (L) cpu.r[14] = cpu.r[15] - 4;
const offset = sext(u32, u24, opcode) << 2;
cpu.r[15] = cpu.r[15] +% offset;
cpu.r[15] +%= sext(u32, u24, opcode) << 2;
cpu.pipe.flush();
}
}.inner;
@ -21,13 +20,8 @@ pub fn branch(comptime L: bool) InstrFn {
pub fn branchAndExchange(cpu: *Arm7tdmi, _: *Bus, opcode: u32) void {
const rn = opcode & 0xF;
if (cpu.r[rn] & 1 == 1) {
cpu.r[15] = cpu.r[rn] & ~@as(u32, 1);
cpu.cpsr.t.set();
} else {
cpu.r[15] = cpu.r[rn] & ~@as(u32, 3);
cpu.cpsr.t.unset();
}
const thumb = cpu.r[rn] & 1 == 1;
cpu.r[15] = cpu.r[rn] & if (thumb) ~@as(u32, 1) else ~@as(u32, 3);
cpu.cpsr.t.write(thumb);
cpu.pipe.flush();
}

View File

@ -15,8 +15,7 @@ pub fn dataProcessing(comptime I: bool, comptime S: bool, comptime instrKind: u4
// If certain conditions are met, PC is 12 ahead instead of 8
// TODO: What are these conditions? I can't remember
if (!I and opcode >> 4 & 1 == 1) cpu.r[15] += 4;
const op1 = if (rn == 0xF) cpu.fakePC() else cpu.r[rn];
const op1 = cpu.r[rn];
var op2: u32 = undefined;
if (I) {

View File

@ -14,13 +14,8 @@ pub fn singleDataTransfer(comptime I: bool, comptime P: bool, comptime U: bool,
const rn = opcode >> 16 & 0xF;
const rd = opcode >> 12 & 0xF;
var base: u32 = undefined;
if (rn == 0xF) {
base = cpu.fakePC();
if (!L) base += 4; // Offset of 12
} else {
base = cpu.r[rn];
}
// If L is set, there is an offset of 12 from the instruction to the PC
const base = cpu.r[rn] + if (!L) 4 else @as(u32, 0);
const offset = if (I) shifter.immShift(false, cpu, opcode) else opcode & 0xFFF;

View File

@ -9,16 +9,13 @@ pub fn format16(comptime cond: u4) InstrFn {
return struct {
fn inner(cpu: *Arm7tdmi, _: *Bus, opcode: u16) void {
// B
const offset = sext(u32, u8, opcode & 0xFF) << 1;
if (cond == 0xE or cond == 0xF)
cpu.panic("[CPU/THUMB.16] Undefined conditional branch with condition {}", .{cond});
const should_execute = switch (cond) {
0xE, 0xF => cpu.panic("[CPU/THUMB.16] Undefined conditional branch with condition {}", .{cond}),
else => checkCond(cpu.cpsr, cond),
};
if (!checkCond(cpu.cpsr, cond)) return;
if (should_execute) {
cpu.r[15] = (cpu.r[15] + 2) +% offset;
}
cpu.r[15] +%= sext(u32, u8, opcode & 0xFF) << 1;
cpu.pipe.flush();
}
}.inner;
}
@ -41,13 +38,16 @@ pub fn format19(comptime is_low: bool) InstrFn {
if (is_low) {
// Instruction 2
const old_pc = cpu.r[15];
const next_opcode = cpu.r[15] - 2;
cpu.r[15] = cpu.r[14] +% (offset << 1);
cpu.r[14] = old_pc | 1;
cpu.r[14] = next_opcode | 1;
cpu.pipe.flush();
} else {
// Instruction 1
cpu.r[14] = (cpu.r[15] + 2) +% (sext(u32, u11, offset) << 12);
const lr_offset = sext(u32, u11, offset) << 12;
cpu.r[14] = (cpu.r[15] +% lr_offset) & ~@as(u32, 1);
}
}
}.inner;

View File

@ -11,7 +11,9 @@ pub fn format6(comptime rd: u3) InstrFn {
fn inner(cpu: *Arm7tdmi, bus: *Bus, opcode: u16) void {
// LDR
const offset = (opcode & 0xFF) << 2;
cpu.r[rd] = bus.read(u32, (cpu.r[15] + 2 & 0xFFFF_FFFD) + offset);
// Bit 1 of the PC intentionally ignored
cpu.r[rd] = bus.read(u32, (cpu.r[15] & ~@as(u32, 2)) + offset);
}
}.inner;
}

View File

@ -28,7 +28,8 @@ pub fn format5(comptime op: u2, comptime h1: u1, comptime h2: u1) InstrFn {
0b11 => {
// BX
cpu.cpsr.t.write(src & 1 == 1);
cpu.r[15] = src & 0xFFFF_FFFE;
cpu.r[15] = src & ~@as(u32, 1);
cpu.pipe.flush();
},
}
}