chore: progress towards working pipeline
focus on THMB branching and a little bit of ARM data processing
This commit is contained in:
		@@ -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();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
                },
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user