feat: implement IPCSYNC irqs
This commit is contained in:
@@ -22,10 +22,16 @@ wram: *[64 * KiB]u8,
|
||||
vram: *Vram,
|
||||
io: io.Io,
|
||||
|
||||
bios: *[16 * KiB]u8,
|
||||
|
||||
pub fn init(allocator: Allocator, scheduler: *Scheduler, ctx: SharedCtx) !@This() {
|
||||
const wram = try allocator.create([64 * KiB]u8);
|
||||
errdefer allocator.destroy(wram);
|
||||
@memset(wram, 0);
|
||||
errdefer allocator.destroy(wram);
|
||||
|
||||
const bios = try allocator.create([16 * KiB]u8);
|
||||
@memset(bios, 0);
|
||||
errdefer allocator.destroy(bios);
|
||||
|
||||
return .{
|
||||
.main = ctx.main,
|
||||
@@ -34,11 +40,14 @@ pub fn init(allocator: Allocator, scheduler: *Scheduler, ctx: SharedCtx) !@This(
|
||||
.wram = wram,
|
||||
.scheduler = scheduler,
|
||||
.io = io.Io.init(ctx.io),
|
||||
|
||||
.bios = bios,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn deinit(self: *@This(), allocator: Allocator) void {
|
||||
allocator.destroy(self.wram);
|
||||
allocator.destroy(self.bios);
|
||||
}
|
||||
|
||||
pub fn reset(_: *@This()) void {}
|
||||
@@ -64,12 +73,13 @@ fn _read(self: *@This(), comptime T: type, comptime mode: Mode, address: u32) T
|
||||
}
|
||||
|
||||
return switch (aligned_addr) {
|
||||
0x0000_0000...0x01FF_FFFF => readInt(T, self.bios[address & 0x3FFF ..][0..byte_count]),
|
||||
0x0200_0000...0x02FF_FFFF => readInt(T, self.main[aligned_addr & 0x003F_FFFF ..][0..byte_count]),
|
||||
0x0300_0000...0x037F_FFFF => switch (self.io.shr.wramcnt.mode.read()) {
|
||||
0b00 => readInt(T, self.wram[aligned_addr & 0x0000_FFFF ..][0..byte_count]),
|
||||
else => self.shr_wram.read(T, .nds7, aligned_addr),
|
||||
},
|
||||
0x0380_0000...0x0380_FFFF => readInt(T, self.wram[aligned_addr & 0x0000_FFFF ..][0..byte_count]),
|
||||
0x0380_0000...0x03FF_FFFF => readInt(T, self.wram[aligned_addr & 0x0000_FFFF ..][0..byte_count]),
|
||||
0x0400_0000...0x04FF_FFFF => io.read(self, T, aligned_addr),
|
||||
0x0600_0000...0x06FF_FFFF => self.vram.read(T, .nds7, aligned_addr),
|
||||
else => warn("unexpected read: 0x{x:0>8} -> {}", .{ aligned_addr, T }),
|
||||
@@ -97,6 +107,7 @@ fn _write(self: *@This(), comptime T: type, comptime mode: Mode, address: u32, v
|
||||
}
|
||||
|
||||
switch (aligned_addr) {
|
||||
0x0000_0000...0x01FF_FFFF => log.err("tried to read from NDS7 BIOS: 0x{X:0>8}", .{aligned_addr}),
|
||||
0x0200_0000...0x02FF_FFFF => writeInt(T, self.main[aligned_addr & 0x003F_FFFF ..][0..byte_count], value),
|
||||
0x0300_0000...0x037F_FFFF => switch (self.io.shr.wramcnt.mode.read()) {
|
||||
0b00 => writeInt(T, self.wram[aligned_addr & 0x0000_FFFF ..][0..byte_count], value),
|
||||
|
||||
@@ -7,11 +7,36 @@ const Bus = @import("Bus.zig");
|
||||
const SharedCtx = @import("../emu.zig").SharedCtx;
|
||||
const masks = @import("../io.zig").masks;
|
||||
|
||||
const IntEnable = @import("../io.zig").IntEnable;
|
||||
const IntRequest = @import("../io.zig").IntEnable;
|
||||
|
||||
const log = std.log.scoped(.nds7_io);
|
||||
|
||||
pub const Io = struct {
|
||||
shr: *SharedCtx.Io,
|
||||
|
||||
/// Interrupt Master Enable
|
||||
/// Read/Write
|
||||
ime: bool = false,
|
||||
|
||||
/// Interrupt Enable
|
||||
/// Read/Write
|
||||
///
|
||||
/// Caller must cast the `u32` to either `nds7.IntEnable` or `nds9.IntEnable`
|
||||
ie: IntEnable = .{ .raw = 0x0000_0000 },
|
||||
|
||||
/// IF - Interrupt Request
|
||||
/// Read/Write
|
||||
///
|
||||
/// Caller must cast the `u32` to either `nds7.IntRequest` or `nds9.IntRequest`
|
||||
irq: IntRequest = .{ .raw = 0x0000_0000 },
|
||||
|
||||
/// Post Boot Flag
|
||||
/// Read/Write
|
||||
///
|
||||
/// Caller must cast the `u8` to either `nds7.PostFlg` or `nds9.PostFlg`
|
||||
postflg: PostFlag = .in_progress,
|
||||
|
||||
pub fn init(io: *SharedCtx.Io) @This() {
|
||||
return .{ .shr = io };
|
||||
}
|
||||
@@ -20,21 +45,23 @@ pub const Io = struct {
|
||||
pub fn read(bus: *const Bus, comptime T: type, address: u32) T {
|
||||
return switch (T) {
|
||||
u32 => switch (address) {
|
||||
0x0400_0208 => @intFromBool(bus.io.shr.ime),
|
||||
0x0400_0210 => bus.io.shr.ie,
|
||||
0x0400_0214 => bus.io.shr.irq,
|
||||
0x0400_0208 => @intFromBool(bus.io.ime),
|
||||
0x0400_0210 => bus.io.ie.raw,
|
||||
0x0400_0214 => bus.io.irq.raw,
|
||||
|
||||
0x0410_0000 => bus.io.shr.ipc_fifo.recv(.nds7),
|
||||
0x0410_0000 => bus.io.shr.ipc.recv(.nds7),
|
||||
else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }),
|
||||
},
|
||||
u16 => switch (address) {
|
||||
0x0400_0180 => @truncate(bus.io.shr.ipc_fifo._nds7.sync.raw),
|
||||
0x0400_0184 => @truncate(bus.io.shr.ipc_fifo._nds7.cnt.raw),
|
||||
0x0400_0180 => @truncate(bus.io.shr.ipc._nds7.sync.raw),
|
||||
0x0400_0184 => @truncate(bus.io.shr.ipc._nds7.cnt.raw),
|
||||
else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }),
|
||||
},
|
||||
u8 => switch (address) {
|
||||
0x0400_0240 => bus.vram.stat().raw,
|
||||
0x0400_0241 => bus.io.shr.wramcnt.raw,
|
||||
|
||||
0x0400_0300 => @intFromEnum(bus.io.postflg),
|
||||
else => warn("unexpected: read(T: {}, addr: 0x{X:0>8}) {} ", .{ T, address, T }),
|
||||
},
|
||||
else => @compileError(T ++ " is an unsupported bus read type"),
|
||||
@@ -44,19 +71,20 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) T {
|
||||
pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
|
||||
switch (T) {
|
||||
u32 => switch (address) {
|
||||
0x0400_0208 => bus.io.shr.ime = value & 1 == 1,
|
||||
0x0400_0210 => bus.io.shr.ie = value,
|
||||
0x0400_0214 => bus.io.shr.irq = value,
|
||||
0x0400_0208 => bus.io.ime = value & 1 == 1,
|
||||
0x0400_0210 => bus.io.ie.raw = value,
|
||||
0x0400_0214 => bus.io.irq.raw &= ~value,
|
||||
|
||||
0x0400_0188 => bus.io.shr.ipc_fifo.send(.nds7, value) catch |e| std.debug.panic("FIFO error: {}", .{e}),
|
||||
0x0400_0188 => bus.io.shr.ipc.send(.nds7, value) catch |e| std.debug.panic("FIFO error: {}", .{e}),
|
||||
else => log.warn("unexpected: write(T: {}, addr: 0x{X:0>8}, value: 0x{X:0>8})", .{ T, address, value }),
|
||||
},
|
||||
u16 => switch (address) {
|
||||
0x0400_0180 => bus.io.shr.ipc_fifo.setIpcSync(.nds7, value),
|
||||
0x0400_0184 => bus.io.shr.ipc_fifo.setIpcFifoCnt(.nds7, value),
|
||||
0x0400_0180 => bus.io.shr.ipc.setIpcSync(.nds7, value),
|
||||
0x0400_0184 => bus.io.shr.ipc.setIpcFifoCnt(.nds7, value),
|
||||
else => log.warn("unexpected: write(T: {}, addr: 0x{X:0>8}, value: 0x{X:0>8})", .{ T, address, value }),
|
||||
},
|
||||
u8 => switch (address) {
|
||||
0x0400_0208 => bus.io.ime = value & 1 == 1,
|
||||
else => log.warn("unexpected: write(T: {}, addr: 0x{X:0>8}, value: 0x{X:0>8})", .{ T, address, value }),
|
||||
},
|
||||
else => @compileError(T ++ " is an unsupported bus write type"),
|
||||
@@ -73,3 +101,5 @@ pub const Vramstat = extern union {
|
||||
vramd_enabled: Bit(u8, 1),
|
||||
raw: u8,
|
||||
};
|
||||
|
||||
const PostFlag = enum(u8) { in_progress = 0, completed };
|
||||
|
||||
Reference in New Issue
Block a user