From bfeedb5310802a708962325818a7db098582606d Mon Sep 17 00:00:00 2001 From: Rekai Musuka Date: Sat, 2 Jul 2022 04:45:34 -0300 Subject: [PATCH] chore: progress towards working pipeline focus on THMB branching and a little bit of ARM data processing --- src/cpu/arm/branch.zig | 14 ++++---------- src/cpu/arm/data_processing.zig | 3 +-- src/cpu/arm/single_data_transfer.zig | 9 ++------- src/cpu/thumb/branch.zig | 22 +++++++++++----------- src/cpu/thumb/data_transfer.zig | 4 +++- src/cpu/thumb/processing_branch.zig | 3 ++- 6 files changed, 23 insertions(+), 32 deletions(-) diff --git a/src/cpu/arm/branch.zig b/src/cpu/arm/branch.zig index 36e73e0..e97fbe6 100644 --- a/src/cpu/arm/branch.zig +++ b/src/cpu/arm/branch.zig @@ -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(); } diff --git a/src/cpu/arm/data_processing.zig b/src/cpu/arm/data_processing.zig index 03480c0..acbfeb0 100644 --- a/src/cpu/arm/data_processing.zig +++ b/src/cpu/arm/data_processing.zig @@ -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) { diff --git a/src/cpu/arm/single_data_transfer.zig b/src/cpu/arm/single_data_transfer.zig index b37706b..c3a1555 100644 --- a/src/cpu/arm/single_data_transfer.zig +++ b/src/cpu/arm/single_data_transfer.zig @@ -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; diff --git a/src/cpu/thumb/branch.zig b/src/cpu/thumb/branch.zig index 2515910..63d6478 100644 --- a/src/cpu/thumb/branch.zig +++ b/src/cpu/thumb/branch.zig @@ -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; diff --git a/src/cpu/thumb/data_transfer.zig b/src/cpu/thumb/data_transfer.zig index ced9813..3a289f4 100644 --- a/src/cpu/thumb/data_transfer.zig +++ b/src/cpu/thumb/data_transfer.zig @@ -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; } diff --git a/src/cpu/thumb/processing_branch.zig b/src/cpu/thumb/processing_branch.zig index c30d7e4..c41d75a 100644 --- a/src/cpu/thumb/processing_branch.zig +++ b/src/cpu/thumb/processing_branch.zig @@ -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(); }, } }