feat(v5te): implement basic DTCM + ITCM
This commit is contained in:
parent
ba22b856ec
commit
ada2a08516
56
src/arm.zig
56
src/arm.zig
|
@ -28,6 +28,8 @@ const condition_lut = [_]u16{
|
|||
};
|
||||
|
||||
pub fn Arm32(comptime arch: Architecture) type {
|
||||
const is_v5te = arch == .v5te;
|
||||
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
|
@ -40,6 +42,10 @@ pub fn Arm32(comptime arch: Architecture) type {
|
|||
|
||||
bank: Bank = Bank.create(),
|
||||
|
||||
// The following will be `void` on.v4t but exist on v5te
|
||||
itcm: if (is_v5te) Itcm else void,
|
||||
dtcm: if (is_v5te) Dtcm else void,
|
||||
|
||||
const arm = switch (arch) {
|
||||
.v4t => @import("arm/v4t.zig").arm,
|
||||
.v5te => @import("arm/v5te.zig").arm,
|
||||
|
@ -153,16 +159,51 @@ pub fn Arm32(comptime arch: Architecture) type {
|
|||
.bus = bus,
|
||||
.cpsr = .{ .raw = 0x0000_001F },
|
||||
.spsr = .{ .raw = 0x0000_0000 },
|
||||
|
||||
.dtcm = if (is_v5te) .{} else {},
|
||||
.itcm = if (is_v5te) .{} else {},
|
||||
};
|
||||
}
|
||||
|
||||
// CPU needs it's own read/write fns due to ICTM and DCTM present in v5te
|
||||
// I considered implementing Bus.cpu_read and Bus.cpu_write but ended up considering that a bit too leaky
|
||||
pub fn read(self: *Self, comptime T: type, address: u32) T {
|
||||
const readInt = std.mem.readIntSliceLittle;
|
||||
|
||||
if (is_v5te) {
|
||||
const itcm_base: u32 = self.itcm.base_address;
|
||||
const itcm_size = self.itcm.buf.len;
|
||||
const dtcm_base: u32 = self.dtcm.base_address;
|
||||
const dtcm_size = self.dtcm.buf.len;
|
||||
|
||||
// FIXME: verify correctness + can this be faster?
|
||||
if (itcm_base < address and address < itcm_base + itcm_size)
|
||||
return readInt(T, self.itcm.buf[address & 0x0000_7FFF ..][0..@sizeOf(T)]);
|
||||
|
||||
if (dtcm_base < address and address < dtcm_base + dtcm_size)
|
||||
return readInt(T, self.itcm.buf[address & 0x0000_3FFF ..][0..@sizeOf(T)]);
|
||||
}
|
||||
|
||||
return self.bus.read(T, address);
|
||||
}
|
||||
|
||||
pub fn write(self: *Self, comptime T: type, address: u32, value: T) void {
|
||||
const writeInt = std.mem.writeIntSliceLittle;
|
||||
|
||||
if (is_v5te) {
|
||||
const itcm_base: u32 = self.itcm.base_address;
|
||||
const itcm_size = self.itcm.buf.len;
|
||||
const dtcm_base: u32 = self.dtcm.base_address;
|
||||
const dtcm_size = self.dtcm.buf.len;
|
||||
|
||||
// FIXME: verify correctness + can this be faster?
|
||||
if (itcm_base < address and address < itcm_base + itcm_size)
|
||||
return writeInt(T, self.itcm.buf[address & 0x0000_7FFF ..][0..@sizeOf(T)], value);
|
||||
|
||||
if (dtcm_base < address and address < dtcm_base + dtcm_size)
|
||||
return writeInt(T, self.itcm.buf[address & 0x0000_3FFF ..][0..@sizeOf(T)], value);
|
||||
}
|
||||
|
||||
return self.bus.write(T, address, value);
|
||||
}
|
||||
|
||||
|
@ -173,6 +214,9 @@ pub fn Arm32(comptime arch: Architecture) type {
|
|||
.bus = self.bus,
|
||||
.cpsr = .{ .raw = 0x0000_001F },
|
||||
.spsr = .{ .raw = 0x0000_0000 },
|
||||
|
||||
.dtcm = if (is_v5te) .{} else {},
|
||||
.itcm = if (is_v5te) .{} else {},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -352,6 +396,18 @@ pub fn Arm32(comptime arch: Architecture) type {
|
|||
};
|
||||
}
|
||||
|
||||
fn Tcm(comptime count: usize, comptime default_addr: u32) type {
|
||||
const KiB = 0x400;
|
||||
|
||||
return struct {
|
||||
buf: [count * KiB]u8 = [_]u8{0x00} ** (count * KiB),
|
||||
base_address: u32 = default_addr,
|
||||
};
|
||||
}
|
||||
|
||||
const Itcm = Tcm(32, 0x0000_0000);
|
||||
const Dtcm = Tcm(16, 0x0080_0000); // GBATEK says default is 0x027C_0000...
|
||||
|
||||
pub const Mode = enum(u5) {
|
||||
User = 0b10000,
|
||||
Fiq = 0b10001,
|
||||
|
|
15
src/lib.zig
15
src/lib.zig
|
@ -321,13 +321,7 @@ test "create ARMv4T interface" {
|
|||
const bus_interface = Bus.init(&bus_impl);
|
||||
const scheduler_interface = Scheduler.init(&scheduler_impl);
|
||||
|
||||
var arm7tdmi = Arm7tdmi{
|
||||
.sched = scheduler_interface,
|
||||
.bus = bus_interface,
|
||||
.cpsr = .{ .raw = 0x0000_001F },
|
||||
.spsr = .{ .raw = 0x0000_0000 },
|
||||
};
|
||||
|
||||
var arm7tdmi = Arm7tdmi.init(scheduler_interface, bus_interface);
|
||||
var icpu = arm7tdmi.interface();
|
||||
|
||||
icpu.reset();
|
||||
|
@ -342,12 +336,7 @@ test "create ARMv5TE interface" {
|
|||
const bus_interface = Bus.init(&bus_impl);
|
||||
const scheduler_interface = Scheduler.init(&scheduler_impl);
|
||||
|
||||
var arm946es = Arm946es{
|
||||
.sched = scheduler_interface,
|
||||
.bus = bus_interface,
|
||||
.cpsr = .{ .raw = 0x0000_001F },
|
||||
.spsr = .{ .raw = 0x0000_0000 },
|
||||
};
|
||||
var arm946es = Arm946es.init(scheduler_interface, bus_interface);
|
||||
|
||||
_ = arm946es.interface();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue