diff --git a/src/arm/cpu/arm/coprocessor.zig b/src/arm/cpu/arm/coprocessor.zig new file mode 100644 index 0000000..4f6186b --- /dev/null +++ b/src/arm/cpu/arm/coprocessor.zig @@ -0,0 +1,50 @@ +const std = @import("std"); +const Bus = @import("../../../lib.zig").Bus; + +const log = std.log.scoped(.coprocessor_handler); + +pub fn dataTransfer(comptime InstrFn: type, comptime P: bool, comptime U: bool, comptime N: bool, comptime W: bool, comptime L: bool) InstrFn { + _ = L; + _ = W; + _ = N; + _ = U; + _ = P; + const Arm32 = @typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?; + + return struct { + fn inner(cpu: Arm32, _: Bus, opcode: u32) void { + _ = cpu; + + log.err("TODO: handle 0x{X:0>8} which is a coprocessor data transfer instr", .{opcode}); + } + }.inner; +} + +pub fn registerTransfer(comptime InstrFn: type, comptime opcode1: u3, comptime L: bool, comptime opcode2: u3) InstrFn { + _ = opcode2; + _ = L; + _ = opcode1; + const Arm32 = @typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?; + + return struct { + fn inner(cpu: Arm32, _: Bus, opcode: u32) void { + _ = cpu; + + log.err("TODO: handle 0x{X:0>8} which is a coprocessor register transfer instr", .{opcode}); + } + }.inner; +} + +pub fn dataProcessing(comptime InstrFn: type, comptime opcode1: u4, comptime opcode2: u3) InstrFn { + _ = opcode2; + _ = opcode1; + const Arm32 = @typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?; + + return struct { + fn inner(cpu: Arm32, _: Bus, opcode: u32) void { + _ = cpu; + + log.err("TODO: handle 0x{X:0>8} which is a coprocessor data processing instr", .{opcode}); + } + }.inner; +} diff --git a/src/arm/v5te.zig b/src/arm/v5te.zig index eee5431..5880e7c 100644 --- a/src/arm/v5te.zig +++ b/src/arm/v5te.zig @@ -18,6 +18,8 @@ pub const arm = struct { const multiply = @import("cpu/arm/multiply.zig").multiply; const multiplyLong = @import("cpu/arm/multiply.zig").multiplyLong; + const cop = @import("cpu/arm/coprocessor.zig"); + /// Determine index into ARM InstrFn LUT pub fn idx(opcode: u32) u12 { // FIXME: omit these? @@ -92,8 +94,29 @@ pub const arm = struct { const L = i >> 8 & 1 == 1; break :blk branch(InstrFn, L); }, - 0b10 => und, // COP Data Transfer - 0b11 => if (i >> 8 & 1 == 1) swi(InstrFn) else und, // COP Data Operation + Register Transfer + 0b10 => blk: { + const P = i >> 8 & 1 == 1; + const U = i >> 7 & 1 == 1; + const N = i >> 6 & 1 == 1; + const W = i >> 5 & 1 == 1; + const L = i >> 4 & 1 == 1; + + break :blk cop.dataTransfer(InstrFn, P, U, N, W, L); + }, + 0b11 => blk: { + if (i >> 8 & 1 == 1) break :blk swi(InstrFn); + + const data_opcode1 = i >> 4 & 0xF; // bits 20 -> 23 + const reg_opcode1 = i >> 5 & 0x7; // bits 21 -> 23 + const opcode2 = i >> 1 & 0x7; // bits 5 -> 7 + const L = i >> 4 & 1 == 1; // bit 20 + + // Bit 4 (index pos of 0) distinguishes between these classes of instructions + break :blk switch (i & 1 == 1) { + true => cop.registerTransfer(InstrFn, reg_opcode1, L, opcode2), + false => cop.dataProcessing(InstrFn, data_opcode1, opcode2), + }; + }, }, }; }