chore: upgrade to zig v0.15.1
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,2 @@
|
|||||||
zig-out/
|
zig-out/
|
||||||
zig-cache/
|
|
||||||
.zig-cache/
|
.zig-cache/
|
||||||
|
|||||||
82
build.zig
82
build.zig
@@ -1,47 +1,75 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
// Although this function looks imperative, note that its job is to
|
// Although this function looks imperative, it does not perform the build
|
||||||
// declaratively construct a build graph that will be executed by an external
|
// directly and instead it mutates the build graph (`b`) that will be then
|
||||||
// runner.
|
// executed by an external runner. The functions in `std.Build` implement a DSL
|
||||||
|
// for defining build steps and express dependencies between them, allowing the
|
||||||
|
// build runner to parallelize the build automatically (and the cache system to
|
||||||
|
// know when a step doesn't need to be re-run).
|
||||||
pub fn build(b: *std.Build) void {
|
pub fn build(b: *std.Build) void {
|
||||||
// Standard target options allows the person running `zig build` to choose
|
// Standard target options allow the person running `zig build` to choose
|
||||||
// what target to build for. Here we do not override the defaults, which
|
// what target to build for. Here we do not override the defaults, which
|
||||||
// means any target is allowed, and the default is native. Other options
|
// means any target is allowed, and the default is native. Other options
|
||||||
// for restricting supported target set are available.
|
// for restricting supported target set are available.
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
|
|
||||||
// Standard optimization options allow the person running `zig build` to select
|
// It's also possible to define more custom flags to toggle optional features
|
||||||
// between Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall. Here we do not
|
// of this build script using `b.option()`. All defined flags (including
|
||||||
// set a preferred release mode, allowing the user to decide how to optimize.
|
// target and optimize options) will be listed when running `zig build --help`
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
// in this directory.
|
||||||
|
|
||||||
const util_dep = b.dependency("zba-util", .{}); // https://git.musuka.dev/paoda/zba-util
|
const zba_util = b.dependency("zba_util", .{});
|
||||||
const bitfield_mod = b.createModule(.{ .root_source_file = b.path("lib/bitfield.zig") }); // https://github.com/FlorenceOS/Florence
|
const bitjuggle = b.dependency("bitjuggle", .{});
|
||||||
|
|
||||||
_ = b.addModule("arm32", .{
|
// This creates a module, which represents a collection of source files alongside
|
||||||
|
// some compilation options, such as optimization mode and linked system libraries.
|
||||||
|
// Zig modules are the preferred way of making Zig code available to consumers.
|
||||||
|
// addModule defines a module that we intend to make available for importing
|
||||||
|
// to our consumers. We must give it a name because a Zig package can expose
|
||||||
|
// multiple modules and consumers will need to be able to specify which
|
||||||
|
// module they want to access.
|
||||||
|
const mod = b.addModule("arm32", .{
|
||||||
|
// The root source file is the "entry point" of this module. Users of
|
||||||
|
// this module will only be able to access public declarations contained
|
||||||
|
// in this file, which means that if you have declarations that you
|
||||||
|
// intend to expose to consumers that were defined in other files part
|
||||||
|
// of this module, you will have to make sure to re-export them from
|
||||||
|
// the root file.
|
||||||
.root_source_file = b.path("src/lib.zig"),
|
.root_source_file = b.path("src/lib.zig"),
|
||||||
|
// Later on we'll use this module as the root module of a test executable
|
||||||
|
// which requires us to specify a target.
|
||||||
|
.target = target,
|
||||||
.imports = &.{
|
.imports = &.{
|
||||||
.{ .name = "zba-util", .module = util_dep.module("zba-util") },
|
.{ .name = "zba_util", .module = zba_util.module("zba_util") },
|
||||||
.{ .name = "bitfield", .module = bitfield_mod },
|
.{ .name = "bitjuggle", .module = bitjuggle.module("bitjuggle") },
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
// Creates a step for unit testing. This only builds the test executable
|
// Creates an executable that will run `test` blocks from the provided module.
|
||||||
// but does not run it.
|
// Here `mod` needs to define a target, which is why earlier we made sure to
|
||||||
const lib_unit_tests = b.addTest(.{
|
// set the releative field.
|
||||||
.root_source_file = b.path("src/lib.zig"),
|
const mod_tests = b.addTest(.{
|
||||||
.target = target,
|
.root_module = mod,
|
||||||
.optimize = optimize,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
lib_unit_tests.root_module.addImport("zba-util", util_dep.module("zba-util"));
|
// A run step that will run the test executable.
|
||||||
lib_unit_tests.root_module.addImport("bitfield", bitfield_mod);
|
const run_mod_tests = b.addRunArtifact(mod_tests);
|
||||||
|
|
||||||
const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests);
|
// A top level step for running all tests. dependOn can be called multiple
|
||||||
|
// times and since the two run steps do not depend on one another, this will
|
||||||
|
// make the two of them run in parallel.
|
||||||
|
const test_step = b.step("test", "Run tests");
|
||||||
|
test_step.dependOn(&run_mod_tests.step);
|
||||||
|
|
||||||
// Similar to creating the run step earlier, this exposes a `test` step to
|
// Just like flags, top level steps are also listed in the `--help` menu.
|
||||||
// the `zig build --help` menu, providing a way for the user to request
|
//
|
||||||
// running the unit tests.
|
// The Zig build system is entirely implemented in userland, which means
|
||||||
const test_step = b.step("test", "Run unit tests");
|
// that it cannot hook into private compiler APIs. All compilation work
|
||||||
test_step.dependOn(&run_lib_unit_tests.step);
|
// orchestrated by the build system will result in other Zig compiler
|
||||||
|
// subcommands being invoked with the right flags defined. You can observe
|
||||||
|
// these invocations when one fails (or you pass a flag to increase
|
||||||
|
// verbosity) to validate assumptions and diagnose problems.
|
||||||
|
//
|
||||||
|
// Lastly, the Zig build system is relatively simple and self-contained,
|
||||||
|
// and reading its source code will allow you to master it.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,17 +6,26 @@
|
|||||||
//
|
//
|
||||||
// It is redundant to include "zig" in this name because it is already
|
// It is redundant to include "zig" in this name because it is already
|
||||||
// within the Zig package namespace.
|
// within the Zig package namespace.
|
||||||
.name = "zba-util",
|
.name = .arm32,
|
||||||
|
|
||||||
// This is a [Semantic Version](https://semver.org/).
|
// This is a [Semantic Version](https://semver.org/).
|
||||||
// In a future version of Zig it will be used for package deduplication.
|
// In a future version of Zig it will be used for package deduplication.
|
||||||
.version = "0.1.0",
|
.version = "0.0.0",
|
||||||
|
// Together with name, this represents a globally unique package
|
||||||
// This field is optional.
|
// identifier. This field is generated by the Zig toolchain when the
|
||||||
// This is currently advisory only; Zig does not yet do anything
|
// package is first created, and then *never changes*. This allows
|
||||||
// with this value.
|
// unambiguous detection of one package being an updated version of
|
||||||
//.minimum_zig_version = "0.11.0",
|
// another.
|
||||||
|
//
|
||||||
|
// When forking a Zig project, this id should be regenerated (delete the
|
||||||
|
// field and run `zig build`) if the upstream project is still maintained.
|
||||||
|
// Otherwise, the fork is *hostile*, attempting to take control over the
|
||||||
|
// original project's identity. Thus it is recommended to leave the comment
|
||||||
|
// on the following line intact, so that it shows up in code reviews that
|
||||||
|
// modify the field.
|
||||||
|
.fingerprint = 0xdff5ad34d5d6f2fb, // Changing this has security and trust implications.
|
||||||
|
// Tracks the earliest Zig version that the package considers to be a
|
||||||
|
// supported use case.
|
||||||
|
.minimum_zig_version = "0.15.1",
|
||||||
// This field is optional.
|
// This field is optional.
|
||||||
// Each dependency must either provide a `url` and `hash`, or a `path`.
|
// Each dependency must either provide a `url` and `hash`, or a `path`.
|
||||||
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
|
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
|
||||||
@@ -27,7 +36,8 @@
|
|||||||
//.example = .{
|
//.example = .{
|
||||||
// // When updating this field to a new URL, be sure to delete the corresponding
|
// // When updating this field to a new URL, be sure to delete the corresponding
|
||||||
// // `hash`, otherwise you are communicating that you expect to find the old hash at
|
// // `hash`, otherwise you are communicating that you expect to find the old hash at
|
||||||
// // the new URL.
|
// // the new URL. If the contents of a URL change this will result in a hash mismatch
|
||||||
|
// // which will prevent zig from using it.
|
||||||
// .url = "https://example.com/foo.tar.gz",
|
// .url = "https://example.com/foo.tar.gz",
|
||||||
//
|
//
|
||||||
// // This is computed from the file contents of the directory of files that is
|
// // This is computed from the file contents of the directory of files that is
|
||||||
@@ -45,18 +55,18 @@
|
|||||||
// // build root. In this case the package's hash is irrelevant and therefore not
|
// // build root. In this case the package's hash is irrelevant and therefore not
|
||||||
// // computed. This field and `url` are mutually exclusive.
|
// // computed. This field and `url` are mutually exclusive.
|
||||||
// .path = "foo",
|
// .path = "foo",
|
||||||
|
//
|
||||||
// // When this is set to `true`, a package is declared to be lazily
|
// // When this is set to `true`, a package is declared to be lazily
|
||||||
// // fetched. This makes the dependency only get fetched if it is
|
// // fetched. This makes the dependency only get fetched if it is
|
||||||
// // actually used.
|
// // actually used.
|
||||||
// .lazy = false,
|
// .lazy = false,
|
||||||
//},
|
//},
|
||||||
.@"zba-util" = .{
|
.zba_util = .{ .path = "../zba-util" },
|
||||||
.url = "https://git.musuka.dev/paoda/zba-util/archive/bf0e744047ce1ec90172dbcc0c72bfcc29a063e3.tar.gz",
|
.bitjuggle = .{
|
||||||
.hash = "1220d044ecfbeacc3b3cebeff131d587e24167d61435a3cb96dffd4d4521bb06aed0",
|
.url = "git+https://github.com/leecannon/zig-bitjuggle#80111f4f8c672aaea94a8a189ae2a7c8bbaf883f",
|
||||||
|
.hash = "bitjuggle-2.0.0-SJdU76dvAAARompHEhqKDiwZ4FE4FZ8eHvPvmz5JUOS0",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// Specifies the set of files and directories that are included in this package.
|
// Specifies the set of files and directories that are included in this package.
|
||||||
// Only files and directories listed here are included in the `hash` that
|
// Only files and directories listed here are included in the `hash` that
|
||||||
// is computed for this package. Only files listed here will remain on disk
|
// is computed for this package. Only files listed here will remain on disk
|
||||||
@@ -69,7 +79,6 @@
|
|||||||
"build.zig",
|
"build.zig",
|
||||||
"build.zig.zon",
|
"build.zig.zon",
|
||||||
"src",
|
"src",
|
||||||
"lib/bitfield.zig",
|
|
||||||
// For example...
|
// For example...
|
||||||
//"LICENSE",
|
//"LICENSE",
|
||||||
//"README.md",
|
//"README.md",
|
||||||
|
|||||||
146
lib/bitfield.zig
146
lib/bitfield.zig
@@ -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 extern 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 @as(ValueType, @bitCast(@as(u1, @truncate(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 (@as(bool, @bitCast(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 extern struct {
|
|
||||||
dummy: FieldType,
|
|
||||||
|
|
||||||
fn field(self: anytype) PtrCastPreserveCV(@This(), @TypeOf(self), FieldType) {
|
|
||||||
return @as(PtrCastPreserveCV(@This(), @TypeOf(self), FieldType), @ptrCast(self));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write(self: anytype, val: ValueType) void {
|
|
||||||
self.field().* &= ~self_mask;
|
|
||||||
self.field().* |= @as(FieldType, @intCast(val)) << shamt;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read(self: anytype) ValueType {
|
|
||||||
const val: FieldType = self.field().*;
|
|
||||||
return @as(ValueType, @intCast((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);
|
|
||||||
}
|
|
||||||
49
src/arm.zig
49
src/arm.zig
@@ -6,8 +6,8 @@ const Bus = @import("lib.zig").Bus;
|
|||||||
const Scheduler = @import("lib.zig").Scheduler;
|
const Scheduler = @import("lib.zig").Scheduler;
|
||||||
const Coprocessor = @import("lib.zig").Coprocessor;
|
const Coprocessor = @import("lib.zig").Coprocessor;
|
||||||
|
|
||||||
const Bitfield = @import("bitfield").Bitfield;
|
const Bitfield = @import("bitjuggle").Bitfield;
|
||||||
const Bit = @import("bitfield").Bit;
|
const Bit = @import("bitjuggle").Boolean;
|
||||||
|
|
||||||
fn condition_lut(comptime isa: Architecture) [16]u16 {
|
fn condition_lut(comptime isa: Architecture) [16]u16 {
|
||||||
return [_]u16{
|
return [_]u16{
|
||||||
@@ -158,11 +158,10 @@ pub fn Arm32(comptime isa: Architecture) type {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: Is this a hack or idiomatic?
|
pub const init = if (is_v5te) init9 else init7;
|
||||||
// See https://github.com/ziglang/zig/blob/1a0e6bcdb140c844384d62b78a7f4247753f9ffd/lib/std/atomic/Atomic.zig#L156-L176
|
pub const reset = if (is_v5te) reset9 else reset7;
|
||||||
pub usingnamespace if (is_v5te) struct {
|
|
||||||
// FIXME: this is pretty NDS9 specific lol
|
fn init9(scheduler: Scheduler, bus: Bus, cp15: Coprocessor) Self {
|
||||||
pub fn init(scheduler: Scheduler, bus: Bus, cp15: Coprocessor) Self {
|
|
||||||
return .{
|
return .{
|
||||||
.sched = scheduler,
|
.sched = scheduler,
|
||||||
.bus = bus,
|
.bus = bus,
|
||||||
@@ -175,21 +174,7 @@ pub fn Arm32(comptime isa: Architecture) type {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Resetting disables logging (if enabled)
|
fn init7(scheduler: Scheduler, bus: Bus) Self {
|
||||||
pub fn reset(self: *Self) void {
|
|
||||||
self.* = .{
|
|
||||||
.sched = self.sched,
|
|
||||||
.bus = self.bus,
|
|
||||||
.cpsr = .{ .raw = 0x0000_001F },
|
|
||||||
.spsr = .{ .raw = 0x0000_0000 },
|
|
||||||
|
|
||||||
.dtcm = .{},
|
|
||||||
.itcm = .{},
|
|
||||||
.cp15 = self.cp15,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else struct {
|
|
||||||
pub fn init(scheduler: Scheduler, bus: Bus) Self {
|
|
||||||
return .{
|
return .{
|
||||||
.sched = scheduler,
|
.sched = scheduler,
|
||||||
.bus = bus,
|
.bus = bus,
|
||||||
@@ -203,7 +188,21 @@ pub fn Arm32(comptime isa: Architecture) type {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Resetting disables logging (if enabled)
|
// FIXME: Resetting disables logging (if enabled)
|
||||||
pub fn reset(self: *Self) void {
|
fn reset9(self: *Self) void {
|
||||||
|
self.* = .{
|
||||||
|
.sched = self.sched,
|
||||||
|
.bus = self.bus,
|
||||||
|
.cpsr = .{ .raw = 0x0000_001F },
|
||||||
|
.spsr = .{ .raw = 0x0000_0000 },
|
||||||
|
|
||||||
|
.dtcm = .{},
|
||||||
|
.itcm = .{},
|
||||||
|
.cp15 = self.cp15,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// FIXME: Resetting disables logging (if enabled)
|
||||||
|
fn reset7(self: *Self) void {
|
||||||
self.* = .{
|
self.* = .{
|
||||||
.sched = self.sched,
|
.sched = self.sched,
|
||||||
.bus = self.bus,
|
.bus = self.bus,
|
||||||
@@ -215,7 +214,6 @@ pub fn Arm32(comptime isa: Architecture) type {
|
|||||||
.cp15 = {},
|
.cp15 = {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
pub fn dbgRead(self: *const Self, comptime T: type, address: u32) T {
|
pub fn dbgRead(self: *const Self, comptime T: type, address: u32) T {
|
||||||
if (is_v5te) {
|
if (is_v5te) {
|
||||||
@@ -410,7 +408,8 @@ pub fn Arm32(comptime isa: Architecture) type {
|
|||||||
std.debug.print("spsr: 0x{X:0>8} ", .{self.spsr.raw});
|
std.debug.print("spsr: 0x{X:0>8} ", .{self.spsr.raw});
|
||||||
self.spsr.toString();
|
self.spsr.toString();
|
||||||
|
|
||||||
std.debug.print("pipeline: {??X:0>8}\n", .{self.pipe.stage});
|
// FIXME(2025-09-22): Formatting here is wrong
|
||||||
|
std.debug.print("pipeline: {any:0>8}\n", .{self.pipe.stage});
|
||||||
|
|
||||||
if (self.cpsr.t.read()) {
|
if (self.cpsr.t.read()) {
|
||||||
const opcode = self.bus.dbgRead(u16, self.r[15] - 4);
|
const opcode = self.bus.dbgRead(u16, self.r[15] - 4);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
pub fn blockDataTransfer(comptime InstrFn: type, comptime P: bool, comptime U: bool, comptime S: bool, comptime W: bool, comptime L: bool) InstrFn {
|
pub fn blockDataTransfer(comptime InstrFn: type, comptime P: bool, comptime U: bool, comptime S: bool, comptime W: bool, comptime L: bool) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u32) void {
|
fn inner(cpu: *Arm32, opcode: u32) void {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const sext = @import("zba-util").sext;
|
const sext = @import("zba_util").sext;
|
||||||
|
|
||||||
pub fn branch(comptime InstrFn: type, comptime L: bool) InstrFn {
|
pub fn branch(comptime InstrFn: type, comptime L: bool) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u32) void {
|
fn inner(cpu: *Arm32, opcode: u32) void {
|
||||||
@@ -29,7 +29,7 @@ pub fn branch(comptime InstrFn: type, comptime L: bool) InstrFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn branchAndExchange(comptime InstrFn: type) InstrFn {
|
pub fn branchAndExchange(comptime InstrFn: type) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
pub fn inner(cpu: *Arm32, opcode: u32) void {
|
pub fn inner(cpu: *Arm32, opcode: u32) void {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Bit = @import("bitfield").Bit;
|
const Bit = @import("bitjuggle").Boolean;
|
||||||
|
|
||||||
const log = std.log.scoped(.coprocessor_handler);
|
const log = std.log.scoped(.coprocessor_handler);
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ pub fn dataTransfer(
|
|||||||
comptime W: bool,
|
comptime W: bool,
|
||||||
comptime L: bool,
|
comptime L: bool,
|
||||||
) InstrFn {
|
) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u32) void {
|
fn inner(cpu: *Arm32, opcode: u32) void {
|
||||||
@@ -80,7 +80,7 @@ pub fn dataTransfer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn registerTransfer(comptime InstrFn: type, comptime opcode1: u3, comptime L: bool, comptime opcode2: u3) InstrFn {
|
pub fn registerTransfer(comptime InstrFn: type, comptime opcode1: u3, comptime L: bool, comptime opcode2: u3) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u32) void {
|
fn inner(cpu: *Arm32, opcode: u32) void {
|
||||||
@@ -147,7 +147,7 @@ pub fn registerTransfer(comptime InstrFn: type, comptime opcode1: u3, comptime L
|
|||||||
pub fn dataProcessing(comptime InstrFn: type, comptime opcode1: u4, comptime opcode2: u3) InstrFn {
|
pub fn dataProcessing(comptime InstrFn: type, comptime opcode1: u4, comptime opcode2: u3) InstrFn {
|
||||||
_ = opcode2;
|
_ = opcode2;
|
||||||
_ = opcode1;
|
_ = opcode1;
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u32) void {
|
fn inner(cpu: *Arm32, opcode: u32) void {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const exec = @import("../barrel_shifter.zig").exec;
|
|||||||
const ror = @import("../barrel_shifter.zig").ror;
|
const ror = @import("../barrel_shifter.zig").ror;
|
||||||
|
|
||||||
pub fn dataProcessing(comptime InstrFn: type, comptime I: bool, comptime S: bool, comptime kind: u4) InstrFn {
|
pub fn dataProcessing(comptime InstrFn: type, comptime I: bool, comptime S: bool, comptime kind: u4) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u32) void {
|
fn inner(cpu: *Arm32, opcode: u32) void {
|
||||||
@@ -153,7 +153,7 @@ pub fn dataProcessing(comptime InstrFn: type, comptime I: bool, comptime S: bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn undefinedTestBehaviour(cpu: *Arm32) void {
|
fn undefinedTestBehaviour(cpu: *Arm32) void {
|
||||||
@setCold(true);
|
@branchHint(.cold);
|
||||||
cpu.setCpsr(cpu.spsr.raw);
|
cpu.setCpsr(cpu.spsr.raw);
|
||||||
}
|
}
|
||||||
}.inner;
|
}.inner;
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const sext = @import("zba-util").sext;
|
const sext = @import("zba_util").sext;
|
||||||
const rotr = @import("zba-util").rotr;
|
const rotr = @import("zba_util").rotr;
|
||||||
|
|
||||||
const log = std.log.scoped(.half_and_signed_data_transfer);
|
const log = std.log.scoped(.half_and_signed_data_transfer);
|
||||||
|
|
||||||
pub fn halfAndSignedDataTransfer(comptime InstrFn: type, comptime P: bool, comptime U: bool, comptime I: bool, comptime W: bool, comptime L: bool) InstrFn {
|
pub fn halfAndSignedDataTransfer(comptime InstrFn: type, comptime P: bool, comptime U: bool, comptime I: bool, comptime W: bool, comptime L: bool) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u32) void {
|
fn inner(cpu: *Arm32, opcode: u32) void {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
pub fn multiply(comptime InstrFn: type, comptime L: bool, comptime U: bool, comptime A: bool, comptime S: bool) InstrFn {
|
pub fn multiply(comptime InstrFn: type, comptime L: bool, comptime U: bool, comptime A: bool, comptime S: bool) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u32) void {
|
fn inner(cpu: *Arm32, opcode: u32) void {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const PSR = @import("../../../arm.zig").PSR;
|
const PSR = @import("../../../arm.zig").PSR;
|
||||||
const rotr = @import("zba-util").rotr;
|
const rotr = @import("zba_util").rotr;
|
||||||
|
|
||||||
const log = std.log.scoped(.ctrl_ext_space);
|
const log = std.log.scoped(.ctrl_ext_space);
|
||||||
|
|
||||||
pub fn control(comptime InstrFn: type, comptime I: bool, comptime op: u6) InstrFn {
|
pub fn control(comptime InstrFn: type, comptime I: bool, comptime op: u6) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u32) void {
|
fn inner(cpu: *Arm32, opcode: u32) void {
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const shifter = @import("../barrel_shifter.zig");
|
const shifter = @import("../barrel_shifter.zig");
|
||||||
|
|
||||||
const rotr = @import("zba-util").rotr;
|
const rotr = @import("zba_util").rotr;
|
||||||
|
|
||||||
pub fn singleDataTransfer(comptime InstrFn: type, comptime I: bool, comptime P: bool, comptime U: bool, comptime B: bool, comptime W: bool, comptime L: bool) InstrFn {
|
pub fn singleDataTransfer(comptime InstrFn: type, comptime I: bool, comptime P: bool, comptime U: bool, comptime B: bool, comptime W: bool, comptime L: bool) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u32) void {
|
fn inner(cpu: *Arm32, opcode: u32) void {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
pub fn armSoftwareInterrupt(comptime InstrFn: type) InstrFn {
|
pub fn armSoftwareInterrupt(comptime InstrFn: type) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, _: u32) void {
|
fn inner(cpu: *Arm32, _: u32) void {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const CPSR = @import("../../arm.zig").PSR;
|
const CPSR = @import("../../arm.zig").PSR;
|
||||||
|
|
||||||
const rotr = @import("zba-util").rotr;
|
const rotr = @import("zba_util").rotr;
|
||||||
|
|
||||||
pub fn exec(comptime S: bool, cpu: anytype, opcode: u32) u32 {
|
pub fn exec(comptime S: bool, cpu: anytype, opcode: u32) u32 {
|
||||||
var result: u32 = undefined;
|
var result: u32 = undefined;
|
||||||
@@ -70,7 +70,7 @@ pub fn immediate(comptime S: bool, cpu: anytype, opcode: u32) u32 {
|
|||||||
|
|
||||||
pub fn lsl(comptime S: bool, cpsr: *CPSR, rm: u32, total_amount: u8) u32 {
|
pub fn lsl(comptime S: bool, cpsr: *CPSR, rm: u32, total_amount: u8) u32 {
|
||||||
const amount: u5 = @truncate(total_amount);
|
const amount: u5 = @truncate(total_amount);
|
||||||
const bit_count: u8 = @typeInfo(u32).Int.bits;
|
const bit_count: u8 = @typeInfo(u32).int.bits;
|
||||||
|
|
||||||
var result: u32 = 0x0000_0000;
|
var result: u32 = 0x0000_0000;
|
||||||
if (total_amount < bit_count) {
|
if (total_amount < bit_count) {
|
||||||
@@ -97,7 +97,7 @@ pub fn lsl(comptime S: bool, cpsr: *CPSR, rm: u32, total_amount: u8) u32 {
|
|||||||
|
|
||||||
pub fn lsr(comptime S: bool, cpsr: *CPSR, rm: u32, total_amount: u32) u32 {
|
pub fn lsr(comptime S: bool, cpsr: *CPSR, rm: u32, total_amount: u32) u32 {
|
||||||
const amount: u5 = @truncate(total_amount);
|
const amount: u5 = @truncate(total_amount);
|
||||||
const bit_count: u8 = @typeInfo(u32).Int.bits;
|
const bit_count: u8 = @typeInfo(u32).int.bits;
|
||||||
|
|
||||||
var result: u32 = 0x0000_0000;
|
var result: u32 = 0x0000_0000;
|
||||||
if (total_amount < bit_count) {
|
if (total_amount < bit_count) {
|
||||||
@@ -121,7 +121,7 @@ pub fn lsr(comptime S: bool, cpsr: *CPSR, rm: u32, total_amount: u32) u32 {
|
|||||||
|
|
||||||
pub fn asr(comptime S: bool, cpsr: *CPSR, rm: u32, total_amount: u8) u32 {
|
pub fn asr(comptime S: bool, cpsr: *CPSR, rm: u32, total_amount: u8) u32 {
|
||||||
const amount: u5 = @truncate(total_amount);
|
const amount: u5 = @truncate(total_amount);
|
||||||
const bit_count: u8 = @typeInfo(u32).Int.bits;
|
const bit_count: u8 = @typeInfo(u32).int.bits;
|
||||||
|
|
||||||
var result: u32 = 0x0000_0000;
|
var result: u32 = 0x0000_0000;
|
||||||
if (total_amount < bit_count) {
|
if (total_amount < bit_count) {
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const asr = @import("../barrel_shifter.zig").asr;
|
|||||||
const ror = @import("../barrel_shifter.zig").ror;
|
const ror = @import("../barrel_shifter.zig").ror;
|
||||||
|
|
||||||
pub fn fmt4(comptime InstrFn: type, comptime op: u4) InstrFn {
|
pub fn fmt4(comptime InstrFn: type, comptime op: u4) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
pub fn fmt14(comptime InstrFn: type, comptime L: bool, comptime R: bool) InstrFn {
|
pub fn fmt14(comptime InstrFn: type, comptime L: bool, comptime R: bool) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
@@ -47,7 +47,7 @@ pub fn fmt14(comptime InstrFn: type, comptime L: bool, comptime R: bool) InstrFn
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt15(comptime InstrFn: type, comptime L: bool, comptime rb: u3) InstrFn {
|
pub fn fmt15(comptime InstrFn: type, comptime L: bool, comptime rb: u3) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
const sext = @import("zba-util").sext;
|
const sext = @import("zba_util").sext;
|
||||||
|
|
||||||
pub fn fmt16(comptime InstrFn: type, comptime cond: u4) InstrFn {
|
pub fn fmt16(comptime InstrFn: type, comptime cond: u4) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
@@ -18,7 +18,7 @@ pub fn fmt16(comptime InstrFn: type, comptime cond: u4) InstrFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn linkExchange(comptime InstrFn: type, comptime H: u2) InstrFn {
|
pub fn linkExchange(comptime InstrFn: type, comptime H: u2) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ const lsr = @import("../barrel_shifter.zig").lsr;
|
|||||||
const asr = @import("../barrel_shifter.zig").asr;
|
const asr = @import("../barrel_shifter.zig").asr;
|
||||||
|
|
||||||
pub fn fmt1(comptime InstrFn: type, comptime op: u2, comptime offset: u5) InstrFn {
|
pub fn fmt1(comptime InstrFn: type, comptime op: u2, comptime offset: u5) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
@@ -53,7 +53,7 @@ pub fn fmt1(comptime InstrFn: type, comptime op: u2, comptime offset: u5) InstrF
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt5(comptime InstrFn: type, comptime op: u2, comptime h1: u1, comptime h2: u1) InstrFn {
|
pub fn fmt5(comptime InstrFn: type, comptime op: u2, comptime h1: u1, comptime h2: u1) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
@@ -119,7 +119,7 @@ pub fn fmt5(comptime InstrFn: type, comptime op: u2, comptime h1: u1, comptime h
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt2(comptime InstrFn: type, comptime I: bool, is_sub: bool, rn: u3) InstrFn {
|
pub fn fmt2(comptime InstrFn: type, comptime I: bool, is_sub: bool, rn: u3) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
@@ -153,7 +153,7 @@ pub fn fmt2(comptime InstrFn: type, comptime I: bool, is_sub: bool, rn: u3) Inst
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt3(comptime InstrFn: type, comptime op: u2, comptime rd: u3) InstrFn {
|
pub fn fmt3(comptime InstrFn: type, comptime op: u2, comptime rd: u3) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
@@ -193,7 +193,7 @@ pub fn fmt3(comptime InstrFn: type, comptime op: u2, comptime rd: u3) InstrFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt12(comptime InstrFn: type, comptime isSP: bool, comptime rd: u3) InstrFn {
|
pub fn fmt12(comptime InstrFn: type, comptime isSP: bool, comptime rd: u3) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
@@ -206,7 +206,7 @@ pub fn fmt12(comptime InstrFn: type, comptime isSP: bool, comptime rd: u3) Instr
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt13(comptime InstrFn: type, comptime S: bool) InstrFn {
|
pub fn fmt13(comptime InstrFn: type, comptime S: bool) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
@@ -218,7 +218,7 @@ pub fn fmt13(comptime InstrFn: type, comptime S: bool) InstrFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn bkpt(comptime InstrFn: type) InstrFn {
|
pub fn bkpt(comptime InstrFn: type) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, _: u16) void {
|
fn inner(cpu: *Arm32, _: u16) void {
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
const rotr = @import("zba-util").rotr;
|
const rotr = @import("zba_util").rotr;
|
||||||
const sext = @import("zba-util").sext;
|
const sext = @import("zba_util").sext;
|
||||||
|
|
||||||
pub fn fmt6(comptime InstrFn: type, comptime rd: u3) InstrFn {
|
pub fn fmt6(comptime InstrFn: type, comptime rd: u3) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
@@ -16,7 +16,7 @@ pub fn fmt6(comptime InstrFn: type, comptime rd: u3) InstrFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt78(comptime InstrFn: type, comptime op: u2, comptime T: bool) InstrFn {
|
pub fn fmt78(comptime InstrFn: type, comptime op: u2, comptime T: bool) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
@@ -90,7 +90,7 @@ pub fn fmt78(comptime InstrFn: type, comptime op: u2, comptime T: bool) InstrFn
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt9(comptime InstrFn: type, comptime B: bool, comptime L: bool, comptime offset: u5) InstrFn {
|
pub fn fmt9(comptime InstrFn: type, comptime B: bool, comptime L: bool, comptime offset: u5) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
@@ -126,7 +126,7 @@ pub fn fmt9(comptime InstrFn: type, comptime B: bool, comptime L: bool, comptime
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt10(comptime InstrFn: type, comptime L: bool, comptime offset: u5) InstrFn {
|
pub fn fmt10(comptime InstrFn: type, comptime L: bool, comptime offset: u5) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
@@ -152,7 +152,7 @@ pub fn fmt10(comptime InstrFn: type, comptime L: bool, comptime offset: u5) Inst
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn fmt11(comptime InstrFn: type, comptime L: bool, comptime rd: u3) InstrFn {
|
pub fn fmt11(comptime InstrFn: type, comptime L: bool, comptime rd: u3) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, opcode: u16) void {
|
fn inner(cpu: *Arm32, opcode: u16) void {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
pub fn fmt17(comptime InstrFn: type) InstrFn {
|
pub fn fmt17(comptime InstrFn: type) InstrFn {
|
||||||
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).Pointer.child).Fn.params[0].type.?).Pointer.child;
|
const Arm32 = @typeInfo(@typeInfo(@typeInfo(InstrFn).pointer.child).@"fn".params[0].type.?).pointer.child;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
fn inner(cpu: *Arm32, _: u16) void {
|
fn inner(cpu: *Arm32, _: u16) void {
|
||||||
|
|||||||
18
src/lib.zig
18
src/lib.zig
@@ -92,9 +92,9 @@ pub const Bus = struct {
|
|||||||
const P = @TypeOf(obj);
|
const P = @TypeOf(obj);
|
||||||
const info = @typeInfo(P);
|
const info = @typeInfo(P);
|
||||||
|
|
||||||
std.debug.assert(info == .Pointer); // `anytype` is a Pointer
|
std.debug.assert(info == .pointer); // `anytype` is a Pointer
|
||||||
std.debug.assert(info.Pointer.size == .One); // Single-Item Pointer
|
std.debug.assert(info.pointer.size == .one); // Single-Item Pointer
|
||||||
std.debug.assert(@typeInfo(info.Pointer.child) == .Struct); // Pointer Child is a `struct`
|
std.debug.assert(@typeInfo(info.pointer.child) == .@"struct"); // Pointer Child is a `struct`
|
||||||
|
|
||||||
const impl = struct {
|
const impl = struct {
|
||||||
fn read8(ptr: *anyopaque, address: u32) u8 {
|
fn read8(ptr: *anyopaque, address: u32) u8 {
|
||||||
@@ -272,9 +272,9 @@ pub const Coprocessor = struct {
|
|||||||
const P = @TypeOf(obj);
|
const P = @TypeOf(obj);
|
||||||
const info = @typeInfo(P);
|
const info = @typeInfo(P);
|
||||||
|
|
||||||
std.debug.assert(info == .Pointer); // `anytype` is a Pointer
|
std.debug.assert(info == .pointer); // `anytype` is a Pointer
|
||||||
std.debug.assert(info.Pointer.size == .One); // Single-Item Pointer
|
std.debug.assert(info.pointer.size == .one); // Single-Item Pointer
|
||||||
std.debug.assert(@typeInfo(info.Pointer.child) == .Struct); // Pointer Child is a `struct`
|
std.debug.assert(@typeInfo(info.pointer.child) == .@"struct"); // Pointer Child is a `struct`
|
||||||
|
|
||||||
const impl = struct {
|
const impl = struct {
|
||||||
fn read(ptr: *anyopaque, op1: u3, cn: u4, cm: u4, op2: u3) u32 {
|
fn read(ptr: *anyopaque, op1: u3, cn: u4, cm: u4, op2: u3) u32 {
|
||||||
@@ -351,9 +351,9 @@ pub const Scheduler = struct {
|
|||||||
const P = @TypeOf(obj);
|
const P = @TypeOf(obj);
|
||||||
const info = @typeInfo(P);
|
const info = @typeInfo(P);
|
||||||
|
|
||||||
std.debug.assert(info == .Pointer); // `anytype` is a Pointer
|
std.debug.assert(info == .pointer); // `anytype` is a Pointer
|
||||||
std.debug.assert(info.Pointer.size == .One); // Single-Item Pointer
|
std.debug.assert(info.pointer.size == .one); // Single-Item Pointer
|
||||||
std.debug.assert(@typeInfo(info.Pointer.child) == .Struct); // Pointer Child is a `struct`
|
std.debug.assert(@typeInfo(info.pointer.child) == .@"struct"); // Pointer Child is a `struct`
|
||||||
|
|
||||||
const impl = struct {
|
const impl = struct {
|
||||||
fn now(ptr: *anyopaque) u64 {
|
fn now(ptr: *anyopaque) u64 {
|
||||||
|
|||||||
Reference in New Issue
Block a user