Compare commits
No commits in common. "f09f814dc3da03f8a10164360b6d867535aed6c6" and "65c3dd722ce070bf10839c1bbb82f57114a334b9" have entirely different histories.
f09f814dc3
...
65c3dd722c
|
@ -12,10 +12,6 @@ pub fn build(b: *std.build.Builder) void {
|
||||||
const mode = b.standardReleaseOptions();
|
const mode = b.standardReleaseOptions();
|
||||||
|
|
||||||
const exe = b.addExecutable("zba", "src/main.zig");
|
const exe = b.addExecutable("zba", "src/main.zig");
|
||||||
|
|
||||||
// Bitfield type from FlorenceOS: https://github.com/FlorenceOS/
|
|
||||||
exe.addPackage(.{ .name = "bitfield", .path = .{ .path = "./lib/util/bitfield.zig" } });
|
|
||||||
|
|
||||||
exe.setTarget(target);
|
exe.setTarget(target);
|
||||||
exe.setBuildMode(mode);
|
exe.setBuildMode(mode);
|
||||||
exe.install();
|
exe.install();
|
||||||
|
|
|
@ -1,146 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
|
|
||||||
fn PtrCastPreserveCV(comptime T: type, comptime PtrToT: type, comptime NewT: type) type {
|
|
||||||
return switch (PtrToT) {
|
|
||||||
*T => *NewT,
|
|
||||||
*const T => *const NewT,
|
|
||||||
*volatile T => *volatile NewT,
|
|
||||||
*const volatile T => *const volatile NewT,
|
|
||||||
|
|
||||||
else => @compileError("wtf you doing"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn BitType(comptime FieldType: type, comptime ValueType: type, comptime shamt: usize) type {
|
|
||||||
const self_bit: FieldType = (1 << shamt);
|
|
||||||
|
|
||||||
return struct {
|
|
||||||
bits: Bitfield(FieldType, shamt, 1),
|
|
||||||
|
|
||||||
pub fn set(self: anytype) void {
|
|
||||||
self.bits.field().* |= self_bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn unset(self: anytype) void {
|
|
||||||
self.bits.field().* &= ~self_bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read(self: anytype) ValueType {
|
|
||||||
return @bitCast(ValueType, @truncate(u1, self.bits.field().* >> shamt));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Since these are mostly used with MMIO, I want to avoid
|
|
||||||
// reading the memory just to write it again, also races
|
|
||||||
pub fn write(self: anytype, val: ValueType) void {
|
|
||||||
if (@bitCast(bool, val)) {
|
|
||||||
self.set();
|
|
||||||
} else {
|
|
||||||
self.unset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Original Bit Constructor
|
|
||||||
// pub fn Bit(comptime FieldType: type, comptime shamt: usize) type {
|
|
||||||
// return BitType(FieldType, u1, shamt);
|
|
||||||
// }
|
|
||||||
|
|
||||||
pub fn Bit(comptime FieldType: type, comptime shamt: usize) type {
|
|
||||||
return BitType(FieldType, bool, shamt);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn Boolean(comptime FieldType: type, comptime shamt: usize) type {
|
|
||||||
return BitType(FieldType, bool, shamt);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn Bitfield(comptime FieldType: type, comptime shamt: usize, comptime num_bits: usize) type {
|
|
||||||
if (shamt + num_bits > @bitSizeOf(FieldType)) {
|
|
||||||
@compileError("bitfield doesn't fit");
|
|
||||||
}
|
|
||||||
|
|
||||||
const self_mask: FieldType = ((1 << num_bits) - 1) << shamt;
|
|
||||||
|
|
||||||
const ValueType = std.meta.Int(.unsigned, num_bits);
|
|
||||||
|
|
||||||
return struct {
|
|
||||||
dummy: FieldType,
|
|
||||||
|
|
||||||
fn field(self: anytype) PtrCastPreserveCV(@This(), @TypeOf(self), FieldType) {
|
|
||||||
return @ptrCast(PtrCastPreserveCV(@This(), @TypeOf(self), FieldType), self);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write(self: anytype, val: ValueType) void {
|
|
||||||
self.field().* &= ~self_mask;
|
|
||||||
self.field().* |= @intCast(FieldType, val) << shamt;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read(self: anytype) ValueType {
|
|
||||||
const val: FieldType = self.field().*;
|
|
||||||
return @intCast(ValueType, (val & self_mask) >> shamt);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
test "bit" {
|
|
||||||
const S = extern union {
|
|
||||||
low: Bit(u32, 0),
|
|
||||||
high: Bit(u32, 1),
|
|
||||||
val: u32,
|
|
||||||
};
|
|
||||||
|
|
||||||
std.testing.expect(@sizeOf(S) == 4);
|
|
||||||
std.testing.expect(@bitSizeOf(S) == 32);
|
|
||||||
|
|
||||||
var s: S = .{ .val = 1 };
|
|
||||||
|
|
||||||
std.testing.expect(s.low.read() == 1);
|
|
||||||
std.testing.expect(s.high.read() == 0);
|
|
||||||
|
|
||||||
s.low.write(0);
|
|
||||||
s.high.write(1);
|
|
||||||
|
|
||||||
std.testing.expect(s.val == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "boolean" {
|
|
||||||
const S = extern union {
|
|
||||||
low: Boolean(u32, 0),
|
|
||||||
high: Boolean(u32, 1),
|
|
||||||
val: u32,
|
|
||||||
};
|
|
||||||
|
|
||||||
std.testing.expect(@sizeOf(S) == 4);
|
|
||||||
std.testing.expect(@bitSizeOf(S) == 32);
|
|
||||||
|
|
||||||
var s: S = .{ .val = 2 };
|
|
||||||
|
|
||||||
std.testing.expect(s.low.read() == false);
|
|
||||||
std.testing.expect(s.high.read() == true);
|
|
||||||
|
|
||||||
s.low.write(true);
|
|
||||||
s.high.write(false);
|
|
||||||
|
|
||||||
std.testing.expect(s.val == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "bitfield" {
|
|
||||||
const S = extern union {
|
|
||||||
low: Bitfield(u32, 0, 16),
|
|
||||||
high: Bitfield(u32, 16, 16),
|
|
||||||
val: u32,
|
|
||||||
};
|
|
||||||
|
|
||||||
std.testing.expect(@sizeOf(S) == 4);
|
|
||||||
std.testing.expect(@bitSizeOf(S) == 32);
|
|
||||||
|
|
||||||
var s: S = .{ .val = 0x13376969 };
|
|
||||||
|
|
||||||
std.testing.expect(s.low.read() == 0x6969);
|
|
||||||
std.testing.expect(s.high.read() == 0x1337);
|
|
||||||
|
|
||||||
s.low.write(0x1337);
|
|
||||||
s.high.write(0x6969);
|
|
||||||
|
|
||||||
std.testing.expect(s.val == 0x69691337);
|
|
||||||
}
|
|
12
src/bus.zig
12
src/bus.zig
|
@ -1,25 +1,21 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const Bios = @import("bus/bios.zig").Bios;
|
const GamePak = @import("pak.zig").GamePak;
|
||||||
const GamePak = @import("bus/pak.zig").GamePak;
|
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
|
|
||||||
pub const Bus = struct {
|
pub const Bus = struct {
|
||||||
pak: GamePak,
|
pak: GamePak,
|
||||||
bios: Bios,
|
|
||||||
|
|
||||||
pub fn withPak(alloc: Allocator, path: []const u8) !@This() {
|
pub fn withPak(alloc: Allocator, path: []const u8) !@This() {
|
||||||
return @This(){
|
return @This(){
|
||||||
.pak = try GamePak.fromPath(alloc, path),
|
.pak = try GamePak.fromPath(alloc, path),
|
||||||
// TODO: don't hardcode this + bundle open-sorce Boot ROM
|
|
||||||
.bios = try Bios.fromPath(alloc, "./bin/gba_bios.bin"),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read32(self: *const @This(), addr: u32) u32 {
|
pub fn read32(self: *const @This(), addr: u32) u32 {
|
||||||
return switch (addr) {
|
return switch (addr) {
|
||||||
// General Internal Memory
|
// General Internal Memory
|
||||||
0x0000_0000...0x0000_3FFF => self.bios.get32(@as(usize, addr)),
|
0x0000_0000...0x0000_3FFF => std.debug.panic("read32 from 0x{X:} in BIOS", .{addr}),
|
||||||
0x0200_0000...0x0203FFFF => std.debug.panic("read32 from 0x{X:} in IWRAM", .{addr}),
|
0x0200_0000...0x0203FFFF => std.debug.panic("read32 from 0x{X:} in IWRAM", .{addr}),
|
||||||
0x0300_0000...0x0300_7FFF => std.debug.panic("read32 from 0x{X:} in EWRAM", .{addr}),
|
0x0300_0000...0x0300_7FFF => std.debug.panic("read32 from 0x{X:} in EWRAM", .{addr}),
|
||||||
0x0400_0000...0x0400_03FE => std.debug.panic("read32 from 0x{X:} in I/O", .{addr}),
|
0x0400_0000...0x0400_03FE => std.debug.panic("read32 from 0x{X:} in I/O", .{addr}),
|
||||||
|
@ -62,7 +58,7 @@ pub const Bus = struct {
|
||||||
pub fn read16(self: *const @This(), addr: u32) u16 {
|
pub fn read16(self: *const @This(), addr: u32) u16 {
|
||||||
return switch (addr) {
|
return switch (addr) {
|
||||||
// General Internal Memory
|
// General Internal Memory
|
||||||
0x0000_0000...0x0000_3FFF => self.bios.get16(@as(usize, addr)),
|
0x0000_0000...0x0000_3FFF => std.debug.panic("read16 from 0x{X:} in BIOS", .{addr}),
|
||||||
0x0200_0000...0x0203FFFF => std.debug.panic("read16 from 0x{X:} in IWRAM", .{addr}),
|
0x0200_0000...0x0203FFFF => std.debug.panic("read16 from 0x{X:} in IWRAM", .{addr}),
|
||||||
0x0300_0000...0x0300_7FFF => std.debug.panic("read16 from 0x{X:} in EWRAM", .{addr}),
|
0x0300_0000...0x0300_7FFF => std.debug.panic("read16 from 0x{X:} in EWRAM", .{addr}),
|
||||||
0x0400_0000...0x0400_03FE => std.debug.panic("read16 from 0x{X:} in I/O", .{addr}),
|
0x0400_0000...0x0400_03FE => std.debug.panic("read16 from 0x{X:} in I/O", .{addr}),
|
||||||
|
@ -105,7 +101,7 @@ pub const Bus = struct {
|
||||||
pub fn read8(self: *const @This(), addr: u32) u8 {
|
pub fn read8(self: *const @This(), addr: u32) u8 {
|
||||||
return switch (addr) {
|
return switch (addr) {
|
||||||
// General Internal Memory
|
// General Internal Memory
|
||||||
0x0000_0000...0x0000_3FFF => self.bios.get8(@as(usize, addr)),
|
0x0000_0000...0x0000_3FFF => std.debug.panic("read8 from 0x{X:} in BIOS", .{addr}),
|
||||||
0x0200_0000...0x0203FFFF => std.debug.panic("read8 from 0x{X:} in IWRAM", .{addr}),
|
0x0200_0000...0x0203FFFF => std.debug.panic("read8 from 0x{X:} in IWRAM", .{addr}),
|
||||||
0x0300_0000...0x0300_7FFF => std.debug.panic("read8 from 0x{X:} in EWRAM", .{addr}),
|
0x0300_0000...0x0300_7FFF => std.debug.panic("read8 from 0x{X:} in EWRAM", .{addr}),
|
||||||
0x0400_0000...0x0400_03FE => std.debug.panic("read8 from 0x{X:} in I/O", .{addr}),
|
0x0400_0000...0x0400_03FE => std.debug.panic("read8 from 0x{X:} in I/O", .{addr}),
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
const std = @import("std");
|
|
||||||
|
|
||||||
const Allocator = std.mem.Allocator;
|
|
||||||
|
|
||||||
pub const Bios = struct {
|
|
||||||
buf: []u8,
|
|
||||||
|
|
||||||
pub fn fromPath(alloc: Allocator, path: []const u8) !@This() {
|
|
||||||
const file = try std.fs.cwd().openFile(path, .{ .read = true });
|
|
||||||
defer file.close();
|
|
||||||
|
|
||||||
const len = try file.getEndPos();
|
|
||||||
|
|
||||||
return @This(){
|
|
||||||
.buf = try file.readToEndAlloc(alloc, len),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub inline fn get32(self: *const @This(), idx: usize) u32 {
|
|
||||||
return (@as(u32, self.buf[idx + 3]) << 24) | (@as(u32, self.buf[idx + 2]) << 16) | (@as(u32, self.buf[idx + 1]) << 8) | (@as(u32, self.buf[idx]));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub inline fn get16(self: *const @This(), idx: usize) u16 {
|
|
||||||
return (@as(u16, self.buf[idx + 1]) << 8) | @as(u16, self.buf[idx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub inline fn get8(self: *const @This(), idx: usize) u8 {
|
|
||||||
return self.buf[idx];
|
|
||||||
}
|
|
||||||
};
|
|
118
src/cpu.zig
118
src/cpu.zig
|
@ -1,11 +1,7 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const util = @import("util.zig");
|
const util = @import("util.zig");
|
||||||
const bitfield = @import("bitfield");
|
|
||||||
|
|
||||||
const Bus = @import("bus.zig").Bus;
|
const Bus = @import("bus.zig").Bus;
|
||||||
const Scheduler = @import("scheduler.zig").Scheduler;
|
const Scheduler = @import("scheduler.zig").Scheduler;
|
||||||
const Bitfield = bitfield.Bitfield;
|
|
||||||
const Bit = bitfield.Bit;
|
|
||||||
|
|
||||||
const comptimeDataProcessing = @import("cpu/data_processing.zig").comptimeDataProcessing;
|
const comptimeDataProcessing = @import("cpu/data_processing.zig").comptimeDataProcessing;
|
||||||
const comptimeSingleDataTransfer = @import("cpu/single_data_transfer.zig").comptimeSingleDataTransfer;
|
const comptimeSingleDataTransfer = @import("cpu/single_data_transfer.zig").comptimeSingleDataTransfer;
|
||||||
|
@ -25,12 +21,11 @@ pub const Arm7tdmi = struct {
|
||||||
.r = [_]u32{0x00} ** 16,
|
.r = [_]u32{0x00} ** 16,
|
||||||
.sch = scheduler,
|
.sch = scheduler,
|
||||||
.bus = bus,
|
.bus = bus,
|
||||||
.cpsr = .{ .val = 0x0000_00DF },
|
.cpsr = .{ .inner = 0x0000_00DF },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub inline fn step(self: *@This()) u64 {
|
pub inline fn step(self: *@This()) u64 {
|
||||||
std.debug.print("PC: 0x{X:} ", .{self.r[15]});
|
|
||||||
const opcode = self.fetch();
|
const opcode = self.fetch();
|
||||||
std.debug.print("opcode: 0x{X:}\n", .{opcode}); // Debug
|
std.debug.print("opcode: 0x{X:}\n", .{opcode}); // Debug
|
||||||
|
|
||||||
|
@ -56,20 +51,20 @@ fn armIdx(opcode: u32) u12 {
|
||||||
fn checkCond(cpsr: *const CPSR, opcode: u32) bool {
|
fn checkCond(cpsr: *const CPSR, opcode: u32) bool {
|
||||||
// TODO: Should I implement an enum?
|
// TODO: Should I implement an enum?
|
||||||
return switch (@truncate(u4, opcode >> 28)) {
|
return switch (@truncate(u4, opcode >> 28)) {
|
||||||
0x0 => cpsr.z.read(), // EQ - Equal
|
0x0 => cpsr.z(), // EQ - Equal
|
||||||
0x1 => !cpsr.z.read(), // NEQ - Not equal
|
0x1 => !cpsr.z(), // NEQ - Not equal
|
||||||
0x2 => cpsr.c.read(), // CS - Unsigned higher or same
|
0x2 => cpsr.c(), // CS - Unsigned higher or same
|
||||||
0x3 => !cpsr.c.read(), // CC - Unsigned lower
|
0x3 => !cpsr.c(), // CC - Unsigned lower
|
||||||
0x4 => cpsr.n.read(), // MI - Negative
|
0x4 => cpsr.n(), // MI - Negative
|
||||||
0x5 => !cpsr.n.read(), // PL - Positive or zero
|
0x5 => !cpsr.n(), // PL - Positive or zero
|
||||||
0x6 => cpsr.v.read(), // VS - Overflow
|
0x6 => cpsr.v(), // VS - Overflow
|
||||||
0x7 => !cpsr.v.read(), // VC - No overflow
|
0x7 => !cpsr.v(), // VC - No overflow
|
||||||
0x8 => cpsr.c.read() and !cpsr.z.read(), // HI - unsigned higher
|
0x8 => cpsr.c() and !cpsr.z(), // HI - unsigned higher
|
||||||
0x9 => !cpsr.c.read() and cpsr.z.read(), // LS - unsigned lower or same
|
0x9 => !cpsr.c() and cpsr.z(), // LS - unsigned lower or same
|
||||||
0xA => cpsr.n.read() == cpsr.v.read(), // GE - Greater or equal
|
0xA => cpsr.n() == cpsr.v(), // GE - Greater or equal
|
||||||
0xB => cpsr.n.read() != cpsr.v.read(), // LT - Less than
|
0xB => cpsr.n() != cpsr.v(), // LT - Less than
|
||||||
0xC => !cpsr.z.read() and (cpsr.n.read() == cpsr.z.read()), // GT - Greater than
|
0xC => !cpsr.z() and (cpsr.n() == cpsr.z()), // GT - Greater than
|
||||||
0xD => cpsr.z.read() or (cpsr.n.read() != cpsr.v.read()), // LE - Less than or equal
|
0xD => cpsr.z() or (cpsr.n() != cpsr.v()), // LE - Less than or equal
|
||||||
0xE => true, // AL - Always
|
0xE => true, // AL - Always
|
||||||
0xF => std.debug.panic("0xF is a reserved condition field", .{}),
|
0xF => std.debug.panic("0xF is a reserved condition field", .{}),
|
||||||
};
|
};
|
||||||
|
@ -121,16 +116,79 @@ fn populate() [0x1000]InstrFn {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const CPSR = extern union {
|
const CPSR = struct {
|
||||||
mode: Bitfield(u32, 0, 5),
|
inner: u32,
|
||||||
t: Bit(u32, 5),
|
|
||||||
f: Bit(u32, 6),
|
pub fn n(self: *const @This()) bool {
|
||||||
i: Bit(u32, 7),
|
return self.inner >> 31 & 1 == 1;
|
||||||
v: Bit(u32, 28),
|
}
|
||||||
c: Bit(u32, 29),
|
|
||||||
z: Bit(u32, 30),
|
pub fn setN(self: *@This(), set: bool) void {
|
||||||
n: Bit(u32, 31),
|
self.setBit(31, set);
|
||||||
val: u32,
|
}
|
||||||
|
|
||||||
|
pub fn z(self: *const @This()) bool {
|
||||||
|
return self.inner >> 30 & 1 == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setZ(self: *@This(), set: bool) void {
|
||||||
|
self.setBit(30, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn c(self: *const @This()) bool {
|
||||||
|
return self.inner >> 29 & 1 == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setC(self: *@This(), set: bool) void {
|
||||||
|
self.setBit(29, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn v(self: *const @This()) bool {
|
||||||
|
return self.inner >> 28 & 1 == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setV(self: *@This(), set: bool) void {
|
||||||
|
self.setBit(28, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn i(self: *const @This()) bool {
|
||||||
|
return self.inner >> 7 & 1 == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setI(self: *@This(), set: bool) void {
|
||||||
|
self.setBit(7, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn f(self: *const @This()) bool {
|
||||||
|
return self.inner >> 6 & 1 == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setF(self: *@This(), set: bool) void {
|
||||||
|
self.setBit(6, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn t(self: *const @This()) bool {
|
||||||
|
return self.inner >> 5 & 1 == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setT(self: *@This(), set: bool) void {
|
||||||
|
self.setBit(5, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mode(self: *const @This()) Mode {
|
||||||
|
return self.inner & 0x1F;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setMode(_: *@This(), _: Mode) void {
|
||||||
|
std.debug.panic("TODO: Implement set_mode for CPSR", .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setBit(self: *@This(), comptime bit: usize, set: bool) void {
|
||||||
|
const set_val = @as(u32, @boolToInt(set)) << bit;
|
||||||
|
const mask = ~(@as(u32, 1) << bit);
|
||||||
|
|
||||||
|
self.inner = (self.inner & mask) | set_val;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const Mode = enum(u5) {
|
const Mode = enum(u5) {
|
||||||
|
|
|
@ -40,10 +40,10 @@ pub fn comptimeDataProcessing(comptime I: bool, comptime S: bool, comptime instr
|
||||||
|
|
||||||
const didOverflow = @subWithOverflow(u32, op1_val, op2, &result);
|
const didOverflow = @subWithOverflow(u32, op1_val, op2, &result);
|
||||||
|
|
||||||
cpu.cpsr.v.write(v_ctx and (result >> 31 & 0x01 == 0x01));
|
cpu.cpsr.setV(v_ctx and (result >> 31 & 0x01 == 0x01));
|
||||||
cpu.cpsr.c.write(didOverflow);
|
cpu.cpsr.setC(didOverflow);
|
||||||
cpu.cpsr.z.write(result == 0x00);
|
cpu.cpsr.setZ(result == 0x00);
|
||||||
cpu.cpsr.n.write(result >> 31 & 0x01 == 0x01);
|
cpu.cpsr.setN(result >> 31 & 0x01 == 0x01);
|
||||||
},
|
},
|
||||||
else => std.debug.panic("TODO: implement data processing type {}", .{instrKind}),
|
else => std.debug.panic("TODO: implement data processing type {}", .{instrKind}),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue