feat: stub coprocessor instructions
This commit is contained in:
		
							
								
								
									
										50
									
								
								src/arm/cpu/arm/coprocessor.zig
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/arm/cpu/arm/coprocessor.zig
									
									
									
									
									
										Normal file
									
								
							| @@ -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; | ||||||
|  | } | ||||||
| @@ -18,6 +18,8 @@ pub const arm = struct { | |||||||
|     const multiply = @import("cpu/arm/multiply.zig").multiply; |     const multiply = @import("cpu/arm/multiply.zig").multiply; | ||||||
|     const multiplyLong = @import("cpu/arm/multiply.zig").multiplyLong; |     const multiplyLong = @import("cpu/arm/multiply.zig").multiplyLong; | ||||||
|  |  | ||||||
|  |     const cop = @import("cpu/arm/coprocessor.zig"); | ||||||
|  |  | ||||||
|     /// Determine index into ARM InstrFn LUT |     /// Determine index into ARM InstrFn LUT | ||||||
|     pub fn idx(opcode: u32) u12 { |     pub fn idx(opcode: u32) u12 { | ||||||
|         // FIXME: omit these? |         // FIXME: omit these? | ||||||
| @@ -92,8 +94,29 @@ pub const arm = struct { | |||||||
|                             const L = i >> 8 & 1 == 1; |                             const L = i >> 8 & 1 == 1; | ||||||
|                             break :blk branch(InstrFn, L); |                             break :blk branch(InstrFn, L); | ||||||
|                         }, |                         }, | ||||||
|                         0b10 => und, // COP Data Transfer |                         0b10 => blk: { | ||||||
|                         0b11 => if (i >> 8 & 1 == 1) swi(InstrFn) else und, // COP Data Operation + Register Transfer |                             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), | ||||||
|  |                             }; | ||||||
|  |                         }, | ||||||
|                     }, |                     }, | ||||||
|                 }; |                 }; | ||||||
|             } |             } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user