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 {
|
pub fn Arm32(comptime arch: Architecture) type {
|
||||||
|
const is_v5te = arch == .v5te;
|
||||||
|
|
||||||
return struct {
|
return struct {
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
|
@ -40,6 +42,10 @@ pub fn Arm32(comptime arch: Architecture) type {
|
||||||
|
|
||||||
bank: Bank = Bank.create(),
|
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) {
|
const arm = switch (arch) {
|
||||||
.v4t => @import("arm/v4t.zig").arm,
|
.v4t => @import("arm/v4t.zig").arm,
|
||||||
.v5te => @import("arm/v5te.zig").arm,
|
.v5te => @import("arm/v5te.zig").arm,
|
||||||
|
@ -153,16 +159,51 @@ pub fn Arm32(comptime arch: Architecture) type {
|
||||||
.bus = bus,
|
.bus = bus,
|
||||||
.cpsr = .{ .raw = 0x0000_001F },
|
.cpsr = .{ .raw = 0x0000_001F },
|
||||||
.spsr = .{ .raw = 0x0000_0000 },
|
.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
|
// 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
|
// 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 {
|
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);
|
return self.bus.read(T, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(self: *Self, comptime T: type, address: u32, value: T) void {
|
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);
|
return self.bus.write(T, address, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,6 +214,9 @@ pub fn Arm32(comptime arch: Architecture) type {
|
||||||
.bus = self.bus,
|
.bus = self.bus,
|
||||||
.cpsr = .{ .raw = 0x0000_001F },
|
.cpsr = .{ .raw = 0x0000_001F },
|
||||||
.spsr = .{ .raw = 0x0000_0000 },
|
.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) {
|
pub const Mode = enum(u5) {
|
||||||
User = 0b10000,
|
User = 0b10000,
|
||||||
Fiq = 0b10001,
|
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 bus_interface = Bus.init(&bus_impl);
|
||||||
const scheduler_interface = Scheduler.init(&scheduler_impl);
|
const scheduler_interface = Scheduler.init(&scheduler_impl);
|
||||||
|
|
||||||
var arm7tdmi = Arm7tdmi{
|
var arm7tdmi = Arm7tdmi.init(scheduler_interface, bus_interface);
|
||||||
.sched = scheduler_interface,
|
|
||||||
.bus = bus_interface,
|
|
||||||
.cpsr = .{ .raw = 0x0000_001F },
|
|
||||||
.spsr = .{ .raw = 0x0000_0000 },
|
|
||||||
};
|
|
||||||
|
|
||||||
var icpu = arm7tdmi.interface();
|
var icpu = arm7tdmi.interface();
|
||||||
|
|
||||||
icpu.reset();
|
icpu.reset();
|
||||||
|
@ -342,12 +336,7 @@ test "create ARMv5TE interface" {
|
||||||
const bus_interface = Bus.init(&bus_impl);
|
const bus_interface = Bus.init(&bus_impl);
|
||||||
const scheduler_interface = Scheduler.init(&scheduler_impl);
|
const scheduler_interface = Scheduler.init(&scheduler_impl);
|
||||||
|
|
||||||
var arm946es = Arm946es{
|
var arm946es = Arm946es.init(scheduler_interface, bus_interface);
|
||||||
.sched = scheduler_interface,
|
|
||||||
.bus = bus_interface,
|
|
||||||
.cpsr = .{ .raw = 0x0000_001F },
|
|
||||||
.spsr = .{ .raw = 0x0000_0000 },
|
|
||||||
};
|
|
||||||
|
|
||||||
_ = arm946es.interface();
|
_ = arm946es.interface();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue