feat: implement basic pipeline
passes arm.gba, thumb.gb and armwrestler, fails in actual games TODO: run FuzzARM debug specific titles
This commit is contained in:
@@ -33,7 +33,8 @@ pub fn fmt14(comptime L: bool, comptime R: bool) InstrFn {
|
||||
if (R) {
|
||||
if (L) {
|
||||
const value = bus.read(u32, address);
|
||||
cpu.r[15] = value & 0xFFFF_FFFE;
|
||||
cpu.r[15] = value & ~@as(u32, 1);
|
||||
cpu.pipe.flush();
|
||||
} else {
|
||||
bus.write(u32, address, cpu.r[14]);
|
||||
}
|
||||
@@ -52,7 +53,13 @@ pub fn fmt15(comptime L: bool, comptime rb: u3) InstrFn {
|
||||
const end_address = cpu.r[rb] + 4 * countRlist(opcode);
|
||||
|
||||
if (opcode & 0xFF == 0) {
|
||||
if (L) cpu.r[15] = bus.read(u32, address) else bus.write(u32, address, cpu.r[15] + 4);
|
||||
if (L) {
|
||||
cpu.r[15] = bus.read(u32, address);
|
||||
cpu.pipe.flush();
|
||||
} else {
|
||||
bus.write(u32, address, cpu.r[15] + 2);
|
||||
}
|
||||
|
||||
cpu.r[rb] += 0x40;
|
||||
return;
|
||||
}
|
||||
|
@@ -9,16 +9,13 @@ pub fn fmt16(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;
|
||||
}
|
||||
@@ -27,8 +24,8 @@ pub fn fmt18() InstrFn {
|
||||
return struct {
|
||||
// B but conditional
|
||||
fn inner(cpu: *Arm7tdmi, _: *Bus, opcode: u16) void {
|
||||
const offset = sext(u32, u11, opcode & 0x7FF) << 1;
|
||||
cpu.r[15] = (cpu.r[15] + 2) +% offset;
|
||||
cpu.r[15] +%= sext(u32, u11, opcode & 0x7FF) << 1;
|
||||
cpu.pipe.flush();
|
||||
}
|
||||
}.inner;
|
||||
}
|
||||
@@ -41,13 +38,16 @@ pub fn fmt19(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;
|
||||
|
@@ -133,10 +133,9 @@ pub fn fmt12(comptime isSP: bool, comptime rd: u3) InstrFn {
|
||||
return struct {
|
||||
fn inner(cpu: *Arm7tdmi, _: *Bus, opcode: u16) void {
|
||||
// ADD
|
||||
const left = if (isSP) cpu.r[13] else (cpu.r[15] + 2) & 0xFFFF_FFFD;
|
||||
const left = if (isSP) cpu.r[13] else cpu.r[15] & ~@as(u32, 2);
|
||||
const right = (opcode & 0xFF) << 2;
|
||||
const result = left + right;
|
||||
cpu.r[rd] = result;
|
||||
cpu.r[rd] = left + right;
|
||||
}
|
||||
}.inner;
|
||||
}
|
||||
|
@@ -11,7 +11,9 @@ pub fn fmt6(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;
|
||||
}
|
||||
|
@@ -6,7 +6,7 @@ pub fn fmt17() InstrFn {
|
||||
return struct {
|
||||
fn inner(cpu: *Arm7tdmi, _: *Bus, _: u16) void {
|
||||
// Copy Values from Current Mode
|
||||
const r15 = cpu.r[15];
|
||||
const ret_addr = cpu.r[15] - 2;
|
||||
const cpsr = cpu.cpsr.raw;
|
||||
|
||||
// Switch Mode
|
||||
@@ -14,9 +14,10 @@ pub fn fmt17() InstrFn {
|
||||
cpu.cpsr.t.write(false); // Force ARM Mode
|
||||
cpu.cpsr.i.write(true); // Disable normal interrupts
|
||||
|
||||
cpu.r[14] = r15; // Resume Execution
|
||||
cpu.r[14] = ret_addr; // Resume Execution
|
||||
cpu.spsr.raw = cpsr; // Previous mode CPSR
|
||||
cpu.r[15] = 0x0000_0008;
|
||||
cpu.pipe.flush();
|
||||
}
|
||||
}.inner;
|
||||
}
|
||||
|
Reference in New Issue
Block a user