Compare commits
2 Commits
472457b9f3
...
2bce02baaa
Author | SHA1 | Date |
---|---|---|
Rekai Nyangadzayi Musuka | 2bce02baaa | |
Rekai Nyangadzayi Musuka | bdebfc0ed7 |
|
@ -335,10 +335,10 @@ fn DmaController(comptime id: u2) type {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pollDmaOnBlank(bus: *Bus, comptime kind: DmaKind) void {
|
pub fn pollDmaOnBlank(bus: *Bus, comptime kind: DmaKind) void {
|
||||||
comptime var i: usize = 0;
|
bus.dma[0].poll(kind);
|
||||||
inline while (i < 4) : (i += 1) {
|
bus.dma[1].poll(kind);
|
||||||
bus.dma[i].poll(kind);
|
bus.dma[2].poll(kind);
|
||||||
}
|
bus.dma[3].poll(kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Adjustment = enum(u2) {
|
const Adjustment = enum(u2) {
|
||||||
|
|
|
@ -72,7 +72,7 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) ?T {
|
||||||
0x0400_0200 => @as(u32, bus.io.irq.raw) << 16 | bus.io.ie.raw,
|
0x0400_0200 => @as(u32, bus.io.irq.raw) << 16 | bus.io.ie.raw,
|
||||||
0x0400_0204 => bus.io.waitcnt.raw,
|
0x0400_0204 => bus.io.waitcnt.raw,
|
||||||
0x0400_0208 => @boolToInt(bus.io.ime),
|
0x0400_0208 => @boolToInt(bus.io.ime),
|
||||||
0x0400_0300 => @enumToInt(bus.io.postflg),
|
|
||||||
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, address }),
|
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, address }),
|
||||||
},
|
},
|
||||||
u16 => switch (address) {
|
u16 => switch (address) {
|
||||||
|
@ -100,11 +100,10 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) ?T {
|
||||||
// Interrupts
|
// Interrupts
|
||||||
0x0400_0200 => bus.io.ie.raw,
|
0x0400_0200 => bus.io.ie.raw,
|
||||||
0x0400_0202 => bus.io.irq.raw,
|
0x0400_0202 => bus.io.irq.raw,
|
||||||
0x0400_0204 => bus.io.waitcnt.raw,
|
0x0400_0204 => @truncate(T, bus.io.waitcnt.raw),
|
||||||
0x0400_0206 => null,
|
0x0400_0206 => null,
|
||||||
0x0400_0208 => @boolToInt(bus.io.ime),
|
0x0400_0208 => @boolToInt(bus.io.ime),
|
||||||
0x0400_020A => null,
|
0x0400_020A => null,
|
||||||
0x0400_0300 => @enumToInt(bus.io.postflg),
|
|
||||||
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, address }),
|
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, address }),
|
||||||
},
|
},
|
||||||
u8 => return switch (address) {
|
u8 => return switch (address) {
|
||||||
|
@ -136,6 +135,7 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) ?T {
|
||||||
0x0400_0206, 0x0400_0207 => null,
|
0x0400_0206, 0x0400_0207 => null,
|
||||||
0x0400_0208, 0x0400_0209 => @truncate(T, @as(u16, @boolToInt(bus.io.ime)) >> getHalf(@truncate(u8, address))),
|
0x0400_0208, 0x0400_0209 => @truncate(T, @as(u16, @boolToInt(bus.io.ime)) >> getHalf(@truncate(u8, address))),
|
||||||
0x0400_020A, 0x0400_020B => null,
|
0x0400_020A, 0x0400_020B => null,
|
||||||
|
|
||||||
0x0400_0300 => @enumToInt(bus.io.postflg),
|
0x0400_0300 => @enumToInt(bus.io.postflg),
|
||||||
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, address }),
|
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, address }),
|
||||||
},
|
},
|
||||||
|
@ -183,12 +183,8 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
|
||||||
|
|
||||||
// Interrupts
|
// Interrupts
|
||||||
0x0400_0200 => bus.io.setIrqs(value),
|
0x0400_0200 => bus.io.setIrqs(value),
|
||||||
0x0400_0204 => bus.io.waitcnt.raw = @truncate(u16, value),
|
0x0400_0204 => bus.io.waitcnt.raw = value,
|
||||||
0x0400_0208 => bus.io.ime = value & 1 == 1,
|
0x0400_0208 => bus.io.ime = value & 1 == 1,
|
||||||
0x0400_0300 => {
|
|
||||||
bus.io.postflg = @intToEnum(PostFlag, value & 1);
|
|
||||||
bus.io.haltcnt = if (value >> 15 & 1 == 0) .Halt else @panic("TODO: Implement STOP");
|
|
||||||
},
|
|
||||||
else => util.io.write.undef(log, "Tried to write 0x{X:0>8}{} to 0x{X:0>8}", .{ value, T, address }),
|
else => util.io.write.undef(log, "Tried to write 0x{X:0>8}{} to 0x{X:0>8}", .{ value, T, address }),
|
||||||
},
|
},
|
||||||
u16 => switch (address) {
|
u16 => switch (address) {
|
||||||
|
@ -232,10 +228,7 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
|
||||||
0x0400_0206 => {},
|
0x0400_0206 => {},
|
||||||
0x0400_0208 => bus.io.ime = value & 1 == 1,
|
0x0400_0208 => bus.io.ime = value & 1 == 1,
|
||||||
0x0400_020A => {},
|
0x0400_020A => {},
|
||||||
0x0400_0300 => {
|
|
||||||
bus.io.postflg = @intToEnum(PostFlag, value & 1);
|
|
||||||
bus.io.haltcnt = if (value >> 15 & 1 == 0) .Halt else @panic("TODO: Implement STOP");
|
|
||||||
},
|
|
||||||
else => util.io.write.undef(log, "Tried to write 0x{X:0>4}{} to 0x{X:0>8}", .{ value, T, address }),
|
else => util.io.write.undef(log, "Tried to write 0x{X:0>4}{} to 0x{X:0>8}", .{ value, T, address }),
|
||||||
},
|
},
|
||||||
u8 => switch (address) {
|
u8 => switch (address) {
|
||||||
|
@ -269,7 +262,7 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
|
||||||
0x0400_0209 => {},
|
0x0400_0209 => {},
|
||||||
0x0400_020A, 0x0400_020B => {},
|
0x0400_020A, 0x0400_020B => {},
|
||||||
|
|
||||||
0x0400_0300 => bus.io.postflg = @intToEnum(PostFlag, value & 1),
|
0x0400_0300 => bus.io.postflg = std.meta.intToEnum(PostFlag, value & 1) catch unreachable,
|
||||||
0x0400_0301 => bus.io.haltcnt = if (value >> 7 & 1 == 0) .Halt else std.debug.panic("TODO: Implement STOP", .{}),
|
0x0400_0301 => bus.io.haltcnt = if (value >> 7 & 1 == 0) .Halt else std.debug.panic("TODO: Implement STOP", .{}),
|
||||||
|
|
||||||
0x0400_0410 => log.debug("Wrote 0x{X:0>2} to the common yet undocumented 0x{X:0>8}", .{ value, address }),
|
0x0400_0410 => log.debug("Wrote 0x{X:0>2} to the common yet undocumented 0x{X:0>8}", .{ value, address }),
|
||||||
|
@ -609,16 +602,16 @@ pub const SoundBias = extern union {
|
||||||
|
|
||||||
/// Read / Write
|
/// Read / Write
|
||||||
pub const WaitControl = extern union {
|
pub const WaitControl = extern union {
|
||||||
sram_cnt: Bitfield(u16, 0, 2),
|
sram_cnt: Bitfield(u32, 0, 2),
|
||||||
s0_first: Bitfield(u16, 2, 2),
|
s0_first: Bitfield(u32, 2, 2),
|
||||||
s0_second: Bit(u16, 4),
|
s0_second: Bit(u32, 4),
|
||||||
s1_first: Bitfield(u16, 5, 2),
|
s1_first: Bitfield(u32, 5, 2),
|
||||||
s1_second: Bit(u16, 7),
|
s1_second: Bit(u32, 7),
|
||||||
s2_first: Bitfield(u16, 8, 2),
|
s2_first: Bitfield(u32, 8, 2),
|
||||||
s2_second: Bit(u16, 10),
|
s2_second: Bit(u32, 10),
|
||||||
phi_out: Bitfield(u16, 11, 2),
|
phi_out: Bitfield(u32, 11, 2),
|
||||||
|
|
||||||
prefetch_enable: Bit(u16, 14),
|
prefetch_enable: Bit(u32, 14),
|
||||||
pak_kind: Bit(u16, 15),
|
pak_kind: Bit(u32, 15),
|
||||||
raw: u16,
|
raw: u32,
|
||||||
};
|
};
|
||||||
|
|
|
@ -190,15 +190,19 @@ fn Timer(comptime id: u2) type {
|
||||||
|
|
||||||
// Perform Cascade Behaviour
|
// Perform Cascade Behaviour
|
||||||
switch (id) {
|
switch (id) {
|
||||||
inline 0, 1, 2 => |idx| {
|
0 => if (cpu.bus.tim[1].cnt.cascade.read()) {
|
||||||
const next = idx + 1;
|
cpu.bus.tim[1]._counter +%= 1;
|
||||||
|
if (cpu.bus.tim[1]._counter == 0) cpu.bus.tim[1].onTimerExpire(cpu, late);
|
||||||
if (cpu.bus.tim[next].cnt.cascade.read()) {
|
|
||||||
cpu.bus.tim[next]._counter +%= 1;
|
|
||||||
if (cpu.bus.tim[next]._counter == 0) cpu.bus.tim[next].onTimerExpire(cpu, late);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
3 => {}, // THere is no timer for TIM3 to cascade to
|
1 => if (cpu.bus.tim[2].cnt.cascade.read()) {
|
||||||
|
cpu.bus.tim[2]._counter +%= 1;
|
||||||
|
if (cpu.bus.tim[2]._counter == 0) cpu.bus.tim[2].onTimerExpire(cpu, late);
|
||||||
|
},
|
||||||
|
2 => if (cpu.bus.tim[3].cnt.cascade.read()) {
|
||||||
|
cpu.bus.tim[3]._counter +%= 1;
|
||||||
|
if (cpu.bus.tim[3]._counter == 0) cpu.bus.tim[3].onTimerExpire(cpu, late);
|
||||||
|
},
|
||||||
|
3 => {}, // There is no Timer for TIM3 to "cascade" to,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reschedule Timer if we're not cascading
|
// Reschedule Timer if we're not cascading
|
||||||
|
|
|
@ -455,12 +455,29 @@ pub const Arm7tdmi = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stepDmaTransfer(self: *Self) bool {
|
pub fn stepDmaTransfer(self: *Self) bool {
|
||||||
comptime var i: usize = 0;
|
const dma0 = &self.bus.dma[0];
|
||||||
inline while (i < 4) : (i += 1) {
|
const dma1 = &self.bus.dma[1];
|
||||||
if (self.bus.dma[i].in_progress) {
|
const dma2 = &self.bus.dma[2];
|
||||||
self.bus.dma[i].step(self);
|
const dma3 = &self.bus.dma[3];
|
||||||
|
|
||||||
|
if (dma0.in_progress) {
|
||||||
|
dma0.step(self);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dma1.in_progress) {
|
||||||
|
dma1.step(self);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma2.in_progress) {
|
||||||
|
dma2.step(self);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma3.in_progress) {
|
||||||
|
dma3.step(self);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -46,7 +46,10 @@ pub const Scheduler = struct {
|
||||||
},
|
},
|
||||||
.TimerOverflow => |id| {
|
.TimerOverflow => |id| {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
inline 0...3 => |idx| cpu.bus.tim[idx].onTimerExpire(cpu, late),
|
0 => cpu.bus.tim[0].onTimerExpire(cpu, late),
|
||||||
|
1 => cpu.bus.tim[1].onTimerExpire(cpu, late),
|
||||||
|
2 => cpu.bus.tim[2].onTimerExpire(cpu, late),
|
||||||
|
3 => cpu.bus.tim[3].onTimerExpire(cpu, late),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.ApuChannel => |id| {
|
.ApuChannel => |id| {
|
||||||
|
|
Loading…
Reference in New Issue