chore: update to latest builtin syntax

This commit is contained in:
2023-07-10 21:20:07 -05:00
parent 954fb279ad
commit d96c9c01ff
25 changed files with 679 additions and 684 deletions

View File

@@ -27,7 +27,7 @@ pub fn read(self: *Self, comptime T: type, r15: u32, address: u32) T {
log.warn("Open Bus! Read from 0x{X:0>8}, but PC was 0x{X:0>8}", .{ address, r15 });
const value = self._read(u32, self.addr_latch);
return @truncate(T, rotr(u32, value, 8 * rotateBy(T, address)));
return @as(T, @truncate(rotr(u32, value, 8 * rotateBy(T, address))));
}
fn rotateBy(comptime T: type, address: u32) u32 {
@@ -43,7 +43,7 @@ pub fn dbgRead(self: *const Self, comptime T: type, r15: u32, address: u32) T {
if (r15 < Self.size) return self._read(T, forceAlign(T, address));
const value = self._read(u32, self.addr_latch);
return @truncate(T, rotr(u32, value, 8 * rotateBy(T, address)));
return @as(T, @truncate(rotr(u32, value, 8 * rotateBy(T, address))));
}
/// Read without the GBA safety checks

View File

@@ -30,7 +30,7 @@ pub fn read(self: *Self, comptime T: type, address: u32) T {
// Addresses 0x0D00_0000 to 0x0DFF_FFFF are reserved for EEPROM accesses if
// * Backup type is EEPROM
// * Small ROM (less than 16MB)
if (@truncate(u8, address >> 24) == 0x0D)
if (@as(u8, @truncate(address >> 24)) == 0x0D)
return self.backup.eeprom.read();
}
}
@@ -77,7 +77,7 @@ inline fn get(self: *const Self, i: u32) u8 {
if (i < self.buf.len) return self.buf[i];
const lhs = i >> 1 & 0xFFFF;
return @truncate(u8, lhs >> 8 * @truncate(u5, i & 1));
return @as(u8, @truncate(lhs >> 8 * @as(u5, @truncate(i & 1))));
}
pub fn dbgRead(self: *const Self, comptime T: type, address: u32) T {
@@ -94,7 +94,7 @@ pub fn dbgRead(self: *const Self, comptime T: type, address: u32) T {
// Addresses 0x0D00_0000 to 0x0DFF_FFFF are reserved for EEPROM accesses if
// * Backup type is EEPROM
// * Small ROM (less than 16MB)
if (@truncate(u8, address >> 24) == 0x0D)
if (@as(u8, @truncate(address >> 24)) == 0x0D)
return self.backup.eeprom.dbgRead();
}
}
@@ -139,7 +139,7 @@ pub fn write(self: *Self, comptime T: type, word_count: u16, address: u32, value
const addr = address & 0x1FF_FFFF;
if (self.backup.kind == .Eeprom) {
const bit = @truncate(u1, value);
const bit = @as(u1, @truncate(value));
if (self.buf.len > 0x100_0000) { // Large
// Addresses 0x1FF_FF00 to 0x1FF_FFFF are reserved from EEPROM accesses if
@@ -151,7 +151,7 @@ pub fn write(self: *Self, comptime T: type, word_count: u16, address: u32, value
// Addresses 0x0D00_0000 to 0x0DFF_FFFF are reserved for EEPROM accesses if
// * Backup type is EEPROM
// * Small ROM (less than 16MB)
if (@truncate(u8, address >> 24) == 0x0D)
if (@as(u8, @truncate(address >> 24)) == 0x0D)
return self.backup.eeprom.write(word_count, &self.backup.buf, bit);
}
}
@@ -159,19 +159,19 @@ pub fn write(self: *Self, comptime T: type, word_count: u16, address: u32, value
switch (T) {
u32 => switch (address) {
0x0800_00C4 => {
self.gpio.write(.Data, @truncate(u4, value));
self.gpio.write(.Direction, @truncate(u4, value >> 16));
self.gpio.write(.Data, @as(u4, @truncate(value)));
self.gpio.write(.Direction, @as(u4, @truncate(value >> 16)));
},
0x0800_00C6 => {
self.gpio.write(.Direction, @truncate(u4, value));
self.gpio.write(.Control, @truncate(u1, value >> 16));
self.gpio.write(.Direction, @as(u4, @truncate(value)));
self.gpio.write(.Control, @as(u1, @truncate(value >> 16)));
},
else => log.err("Wrote {} 0x{X:0>8} to 0x{X:0>8}, Unhandled", .{ T, value, address }),
},
u16 => switch (address) {
0x0800_00C4 => self.gpio.write(.Data, @truncate(u4, value)),
0x0800_00C6 => self.gpio.write(.Direction, @truncate(u4, value)),
0x0800_00C8 => self.gpio.write(.Control, @truncate(u1, value)),
0x0800_00C4 => self.gpio.write(.Data, @as(u4, @truncate(value))),
0x0800_00C6 => self.gpio.write(.Direction, @as(u4, @truncate(value))),
0x0800_00C8 => self.gpio.write(.Control, @as(u1, @truncate(value))),
else => log.err("Wrote {} 0x{X:0>4} to 0x{X:0>8}, Unhandled", .{ T, value, address }),
},
u8 => log.debug("Wrote {} 0x{X:0>2} to 0x{X:0>8}, Ignored.", .{ T, value, address }),

View File

@@ -77,7 +77,7 @@ pub const Backup = struct {
switch (addr) {
0x0000 => if (self.kind == .Flash1M and self.flash.set_bank) {
self.flash.bank = @truncate(u1, byte);
self.flash.bank = @as(u1, @truncate(byte));
},
0x5555 => {
if (self.flash.state == .Command) {

View File

@@ -108,7 +108,7 @@ pub const Eeprom = struct {
switch (self.state) {
.Ready => {
if (self.writer.len() == 2) {
const req = @intCast(u2, self.writer.finish());
const req = @as(u2, @intCast(self.writer.finish()));
switch (req) {
0b11 => self.state = .Read,
0b10 => self.state = .Write,
@@ -120,7 +120,7 @@ pub const Eeprom = struct {
switch (self.kind) {
.Large => {
if (self.writer.len() == 14) {
const addr = @intCast(u10, self.writer.finish());
const addr = @as(u10, @intCast(self.writer.finish()));
const value = std.mem.readIntSliceLittle(u64, buf[@as(u13, addr) * 8 ..][0..8]);
self.reader.configure(value);
@@ -130,7 +130,7 @@ pub const Eeprom = struct {
.Small => {
if (self.writer.len() == 6) {
// FIXME: Duplicated code from above
const addr = @intCast(u6, self.writer.finish());
const addr = @as(u6, @intCast(self.writer.finish()));
const value = std.mem.readIntSliceLittle(u64, buf[@as(u13, addr) * 8 ..][0..8]);
self.reader.configure(value);
@@ -144,13 +144,13 @@ pub const Eeprom = struct {
switch (self.kind) {
.Large => {
if (self.writer.len() == 14) {
self.addr = @intCast(u10, self.writer.finish());
self.addr = @as(u10, @intCast(self.writer.finish()));
self.state = .WriteTransfer;
}
},
.Small => {
if (self.writer.len() == 6) {
self.addr = @intCast(u6, self.writer.finish());
self.addr = @as(u6, @intCast(self.writer.finish()));
self.state = .WriteTransfer;
}
},
@@ -189,8 +189,8 @@ const Reader = struct {
const bit = if (self.i < 4) blk: {
break :blk 0;
} else blk: {
const idx = @intCast(u6, 63 - (self.i - 4));
break :blk @truncate(u1, self.data >> idx);
const idx = @as(u6, @intCast(63 - (self.i - 4)));
break :blk @as(u1, @truncate(self.data >> idx));
};
self.i = (self.i + 1) % (64 + 4);
@@ -205,8 +205,8 @@ const Reader = struct {
const bit = if (self.i < 4) blk: {
break :blk 0;
} else blk: {
const idx = @intCast(u6, 63 - (self.i - 4));
break :blk @truncate(u1, self.data >> idx);
const idx = @as(u6, @intCast(63 - (self.i - 4)));
break :blk @as(u1, @truncate(self.data >> idx));
};
return bit;
@@ -230,7 +230,7 @@ const Writer = struct {
}
fn requestWrite(self: *Self, bit: u1) void {
const idx = @intCast(u1, 1 - self.i);
const idx = @as(u1, @intCast(1 - self.i));
self.data = (self.data & ~(@as(u64, 1) << idx)) | (@as(u64, bit) << idx);
self.i += 1;
}
@@ -244,13 +244,13 @@ const Writer = struct {
.Unknown => unreachable,
};
const idx = @intCast(u4, size - self.i);
const idx = @as(u4, @intCast(size - self.i));
self.data = (self.data & ~(@as(u64, 1) << idx)) | (@as(u64, bit) << idx);
self.i += 1;
}
fn dataWrite(self: *Self, bit: u1) void {
const idx = @intCast(u6, 63 - self.i);
const idx = @as(u6, @intCast(63 - self.i));
self.data = (self.data & ~(@as(u64, 1) << idx)) | (@as(u64, bit) << idx);
self.i += 1;
}

View File

@@ -20,7 +20,7 @@ pub fn create() DmaTuple {
}
pub fn read(comptime T: type, dma: *const DmaTuple, addr: u32) ?T {
const byte_addr = @truncate(u8, addr);
const byte_addr = @as(u8, @truncate(addr));
return switch (T) {
u32 => switch (byte_addr) {
@@ -55,19 +55,19 @@ pub fn read(comptime T: type, dma: *const DmaTuple, addr: u32) ?T {
u8 => switch (byte_addr) {
0xB0...0xB7 => null, // DMA0SAD, DMA0DAD
0xB8, 0xB9 => 0x00, // DMA0CNT_L
0xBA, 0xBB => @truncate(T, dma.*[0].dmacntH() >> getHalf(byte_addr)),
0xBA, 0xBB => @as(T, @truncate(dma.*[0].dmacntH() >> getHalf(byte_addr))),
0xBC...0xC3 => null, // DMA1SAD, DMA1DAD
0xC4, 0xC5 => 0x00, // DMA1CNT_L
0xC6, 0xC7 => @truncate(T, dma.*[1].dmacntH() >> getHalf(byte_addr)),
0xC6, 0xC7 => @as(T, @truncate(dma.*[1].dmacntH() >> getHalf(byte_addr))),
0xC8...0xCF => null, // DMA2SAD, DMA2DAD
0xD0, 0xD1 => 0x00, // DMA2CNT_L
0xD2, 0xD3 => @truncate(T, dma.*[2].dmacntH() >> getHalf(byte_addr)),
0xD2, 0xD3 => @as(T, @truncate(dma.*[2].dmacntH() >> getHalf(byte_addr))),
0xD4...0xDB => null, // DMA3SAD, DMA3DAD
0xDC, 0xDD => 0x00, // DMA3CNT_L
0xDE, 0xDF => @truncate(T, dma.*[3].dmacntH() >> getHalf(byte_addr)),
0xDE, 0xDF => @as(T, @truncate(dma.*[3].dmacntH() >> getHalf(byte_addr))),
else => util.io.read.err(T, log, "unexpected {} read from 0x{X:0>8}", .{ T, addr }),
},
else => @compileError("DMA: Unsupported read width"),
@@ -75,7 +75,7 @@ pub fn read(comptime T: type, dma: *const DmaTuple, addr: u32) ?T {
}
pub fn write(comptime T: type, dma: *DmaTuple, addr: u32, value: T) void {
const byte_addr = @truncate(u8, addr);
const byte_addr = @as(u8, @truncate(addr));
switch (T) {
u32 => switch (byte_addr) {
@@ -209,7 +209,7 @@ fn DmaController(comptime id: u2) type {
}
pub fn setDmacntL(self: *Self, halfword: u16) void {
self.word_count = @truncate(@TypeOf(self.word_count), halfword);
self.word_count = @as(@TypeOf(self.word_count), @truncate(halfword));
}
pub fn dmacntH(self: *const Self) u16 {
@@ -233,16 +233,16 @@ fn DmaController(comptime id: u2) type {
}
pub fn setDmacnt(self: *Self, word: u32) void {
self.setDmacntL(@truncate(u16, word));
self.setDmacntH(@truncate(u16, word >> 16));
self.setDmacntL(@as(u16, @truncate(word)));
self.setDmacntH(@as(u16, @truncate(word >> 16)));
}
pub fn step(self: *Self, cpu: *Arm7tdmi) void {
const bus_ptr = @ptrCast(*Bus, @alignCast(@alignOf(Bus), cpu.bus.ptr));
const bus_ptr: *Bus = @ptrCast(@alignCast(cpu.bus.ptr));
const is_fifo = (id == 1 or id == 2) and self.cnt.start_timing.read() == 0b11;
const sad_adj = @intToEnum(Adjustment, self.cnt.sad_adj.read());
const dad_adj = if (is_fifo) .Fixed else @intToEnum(Adjustment, self.cnt.dad_adj.read());
const sad_adj = @as(Adjustment, @enumFromInt(self.cnt.sad_adj.read()));
const dad_adj = if (is_fifo) .Fixed else @as(Adjustment, @enumFromInt(self.cnt.dad_adj.read()));
const transfer_type = is_fifo or self.cnt.transfer_type.read();
const offset: u32 = if (transfer_type) @sizeOf(u32) else @sizeOf(u16);
@@ -260,10 +260,10 @@ fn DmaController(comptime id: u2) type {
self.data_latch = value << 16 | value;
}
cpu.bus.write(u16, dad_addr, @truncate(u16, rotr(u32, self.data_latch, 8 * (dad_addr & 3))));
cpu.bus.write(u16, dad_addr, @as(u16, @truncate(rotr(u32, self.data_latch, 8 * (dad_addr & 3)))));
}
switch (@truncate(u8, sad_addr >> 24)) {
switch (@as(u8, @truncate(sad_addr >> 24))) {
// according to fleroviux, DMAs with a source address in ROM misbehave
// the resultant behaviour is that the source address will increment despite what DMAXCNT says
0x08...0x0D => self.sad_latch +%= offset, // obscure behaviour
@@ -321,7 +321,7 @@ fn DmaController(comptime id: u2) type {
// Reload internal DAD latch if we are in IncrementRelaod
if (self.in_progress) {
self._word_count = if (self.word_count == 0) std.math.maxInt(@TypeOf(self._word_count)) else self.word_count;
if (@intToEnum(Adjustment, self.cnt.dad_adj.read()) == .IncrementReload) self.dad_latch = self.dad;
if (@as(Adjustment, @enumFromInt(self.cnt.dad_adj.read())) == .IncrementReload) self.dad_latch = self.dad;
}
}

View File

@@ -31,7 +31,7 @@ pub const Gpio = struct {
fn step(self: *Device, value: u4) u4 {
return switch (self.kind) {
.Rtc => blk: {
const clock = @ptrCast(*Clock, @alignCast(@alignOf(*Clock), self.ptr.?));
const clock: *Clock = @ptrCast(@alignCast(self.ptr.?));
break :blk clock.step(Clock.Data{ .raw = value });
},
.None => value,
@@ -94,7 +94,7 @@ pub const Gpio = struct {
pub fn deinit(self: *Self, allocator: Allocator) void {
switch (self.device.kind) {
.Rtc => allocator.destroy(@ptrCast(*Clock, @alignCast(@alignOf(*Clock), self.device.ptr.?))),
.Rtc => allocator.destroy(@as(*Clock, @ptrCast(@alignCast(self.device.ptr.?)))),
.None => {},
}
@@ -146,16 +146,16 @@ pub const Clock = struct {
/// 2. A `count`, which keeps track of which byte is currently being read
/// 3. An index, which keeps track of which bit of the byte determined by `count` is being read
fn read(self: *Reader, clock: *const Clock, register: Register) u1 {
const idx = @intCast(u3, self.i);
const idx = @as(u3, @intCast(self.i));
defer self.i += 1;
// FIXME: What do I do about the unused bits?
return switch (register) {
.Control => @truncate(u1, switch (self.count) {
.Control => @as(u1, @truncate(switch (self.count) {
0 => clock.cnt.raw >> idx,
else => std.debug.panic("Tried to read from byte #{} of {} (hint: there's only 1 byte)", .{ self.count, register }),
}),
.DateTime => @truncate(u1, switch (self.count) {
})),
.DateTime => @as(u1, @truncate(switch (self.count) {
// Date
0 => clock.year >> idx,
1 => @as(u8, clock.month) >> idx,
@@ -167,13 +167,13 @@ pub const Clock = struct {
5 => @as(u8, clock.minute) >> idx,
6 => @as(u8, clock.second) >> idx,
else => std.debug.panic("Tried to read from byte #{} of {} (hint: there's only 7 bytes)", .{ self.count, register }),
}),
.Time => @truncate(u1, switch (self.count) {
})),
.Time => @as(u1, @truncate(switch (self.count) {
0 => @as(u8, clock.hour) >> idx,
1 => @as(u8, clock.minute) >> idx,
2 => @as(u8, clock.second) >> idx,
else => std.debug.panic("Tried to read from byte #{} of {} (hint: there's only 3 bytes)", .{ self.count, register }),
}),
})),
};
}
@@ -207,7 +207,7 @@ pub const Clock = struct {
/// Append a bit to the internal bit buffer (aka an integer)
fn push(self: *Writer, value: u1) void {
const idx = @intCast(u3, self.i);
const idx = @as(u3, @intCast(self.i));
self.buf = (self.buf & ~(@as(u8, 1) << idx)) | @as(u8, value) << idx;
self.i += 1;
}
@@ -290,22 +290,22 @@ pub const Clock = struct {
.gpio = gpio, // Can't use Arm7tdmi ptr b/c not initialized yet
};
const sched_ptr = @ptrCast(*Scheduler, @alignCast(@alignOf(Scheduler), cpu.sched.ptr));
const sched_ptr: *Scheduler = @ptrCast(@alignCast(cpu.sched.ptr));
sched_ptr.push(.RealTimeClock, 1 << 24); // Every Second
}
pub fn onClockUpdate(self: *Self, late: u64) void {
const sched_ptr = @ptrCast(*Scheduler, @alignCast(@alignOf(Scheduler), self.cpu.sched.ptr));
const sched_ptr: *Scheduler = @ptrCast(@alignCast(self.cpu.sched.ptr));
sched_ptr.push(.RealTimeClock, (1 << 24) -| late); // Reschedule
const now = DateTime.now();
self.year = bcd(@intCast(u8, now.date.year - 2000));
self.month = @truncate(u5, bcd(now.date.month));
self.day = @truncate(u6, bcd(now.date.day));
self.weekday = @truncate(u3, bcd((now.date.weekday() + 1) % 7)); // API is Monday = 0, Sunday = 6. We want Sunday = 0, Saturday = 6
self.hour = @truncate(u6, bcd(now.time.hour));
self.minute = @truncate(u7, bcd(now.time.minute));
self.second = @truncate(u7, bcd(now.time.second));
self.year = bcd(@as(u8, @intCast(now.date.year - 2000)));
self.month = @as(u5, @truncate(bcd(now.date.month)));
self.day = @as(u6, @truncate(bcd(now.date.day)));
self.weekday = @as(u3, @truncate(bcd((now.date.weekday() + 1) % 7))); // API is Monday = 0, Sunday = 6. We want Sunday = 0, Saturday = 6
self.hour = @as(u6, @truncate(bcd(now.time.hour)));
self.minute = @as(u7, @truncate(bcd(now.time.minute)));
self.second = @as(u7, @truncate(bcd(now.time.second)));
}
fn step(self: *Self, value: Data) u4 {
@@ -321,14 +321,14 @@ pub const Clock = struct {
}
}
break :blk @truncate(u4, value.raw);
break :blk @as(u4, @truncate(value.raw));
},
.Command => blk: {
if (!value.cs.read()) log.err("Expected CS to be set during {}, however CS was cleared", .{self.state});
// If SCK rises, sample SIO
if (!cache.sck.read() and value.sck.read()) {
self.writer.push(@boolToInt(value.sio.read()));
self.writer.push(@intFromBool(value.sio.read()));
if (self.writer.finished()) {
self.state = self.processCommand(self.writer.buf);
@@ -338,14 +338,14 @@ pub const Clock = struct {
}
}
break :blk @truncate(u4, value.raw);
break :blk @as(u4, @truncate(value.raw));
},
.Write => |register| blk: {
if (!value.cs.read()) log.err("Expected CS to be set during {}, however CS was cleared", .{self.state});
// If SCK rises, sample SIO
if (!cache.sck.read() and value.sck.read()) {
self.writer.push(@boolToInt(value.sio.read()));
self.writer.push(@intFromBool(value.sio.read()));
const register_width: u32 = switch (register) {
.Control => 1,
@@ -364,7 +364,7 @@ pub const Clock = struct {
}
}
break :blk @truncate(u4, value.raw);
break :blk @as(u4, @truncate(value.raw));
},
.Read => |register| blk: {
if (!value.cs.read()) log.err("Expected CS to be set during {}, however CS was cleared", .{self.state});
@@ -390,7 +390,7 @@ pub const Clock = struct {
}
}
break :blk @truncate(u4, ret.raw);
break :blk @as(u4, @truncate(ret.raw));
},
};
}
@@ -403,7 +403,7 @@ pub const Clock = struct {
}
fn irq(self: *Self) void {
const bus_ptr = @ptrCast(*Bus, @alignCast(@alignOf(Bus), self.cpu.bus.ptr));
const bus_ptr: *Bus = @ptrCast(@alignCast(self.cpu.bus.ptr));
// TODO: Confirm that this is the right behaviour
log.debug("Force GamePak IRQ", .{});
@@ -429,7 +429,7 @@ pub const Clock = struct {
log.debug("Handling Command 0x{X:0>2} [0b{b:0>8}]", .{ command, command });
const is_write = command & 1 == 0;
const rtc_register = @truncate(u3, command >> 1 & 0x7);
const rtc_register = @as(u3, @truncate(command >> 1 & 0x7));
if (is_write) {
return switch (rtc_register) {

View File

@@ -43,8 +43,8 @@ pub const Io = struct {
}
fn setIrqs(self: *Io, word: u32) void {
self.ie.raw = @truncate(u16, word);
self.irq.raw &= ~@truncate(u16, word >> 16);
self.ie.raw = @as(u16, @truncate(word));
self.irq.raw &= ~@as(u16, @truncate(word >> 16));
}
};
@@ -75,8 +75,8 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) ?T {
// Interrupts
0x0400_0200 => @as(u32, bus.io.irq.raw) << 16 | bus.io.ie.raw,
0x0400_0204 => bus.io.waitcnt.raw,
0x0400_0208 => @boolToInt(bus.io.ime),
0x0400_0300 => @enumToInt(bus.io.postflg),
0x0400_0208 => @intFromBool(bus.io.ime),
0x0400_0300 => @intFromEnum(bus.io.postflg),
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, address }),
},
u16 => switch (address) {
@@ -109,9 +109,9 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) ?T {
0x0400_0202 => bus.io.irq.raw,
0x0400_0204 => bus.io.waitcnt.raw,
0x0400_0206 => 0x0000,
0x0400_0208 => @boolToInt(bus.io.ime),
0x0400_0208 => @intFromBool(bus.io.ime),
0x0400_020A => 0x0000,
0x0400_0300 => @enumToInt(bus.io.postflg),
0x0400_0300 => @intFromEnum(bus.io.postflg),
0x0400_0302 => 0x0000,
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, address }),
},
@@ -141,13 +141,13 @@ pub fn read(bus: *const Bus, comptime T: type, address: u32) ?T {
0x0400_015A, 0x0400_015B => 0x00,
// Interrupts
0x0400_0200, 0x0400_0201 => @truncate(T, bus.io.ie.raw >> getHalf(@truncate(u8, address))),
0x0400_0202, 0x0400_0203 => @truncate(T, bus.io.irq.raw >> getHalf(@truncate(u8, address))),
0x0400_0204, 0x0400_0205 => @truncate(T, bus.io.waitcnt.raw >> getHalf(@truncate(u8, address))),
0x0400_0200, 0x0400_0201 => @as(T, @truncate(bus.io.ie.raw >> getHalf(@as(u8, @truncate(address))))),
0x0400_0202, 0x0400_0203 => @as(T, @truncate(bus.io.irq.raw >> getHalf(@as(u8, @truncate(address))))),
0x0400_0204, 0x0400_0205 => @as(T, @truncate(bus.io.waitcnt.raw >> getHalf(@as(u8, @truncate(address))))),
0x0400_0206, 0x0400_0207 => 0x00,
0x0400_0208, 0x0400_0209 => @truncate(T, @as(u16, @boolToInt(bus.io.ime)) >> getHalf(@truncate(u8, address))),
0x0400_0208, 0x0400_0209 => @as(T, @truncate(@as(u16, @intFromBool(bus.io.ime)) >> getHalf(@as(u8, @truncate(address))))),
0x0400_020A, 0x0400_020B => 0x00,
0x0400_0300 => @enumToInt(bus.io.postflg),
0x0400_0300 => @intFromEnum(bus.io.postflg),
0x0400_0301 => null,
0x0400_0302, 0x0400_0303 => 0x00,
else => util.io.read.undef(T, log, "Tried to perform a {} read to 0x{X:0>8}", .{ T, address }),
@@ -196,10 +196,10 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
// Interrupts
0x0400_0200 => bus.io.setIrqs(value),
0x0400_0204 => bus.io.waitcnt.set(@truncate(u16, value)),
0x0400_0204 => bus.io.waitcnt.set(@as(u16, @truncate(value))),
0x0400_0208 => bus.io.ime = value & 1 == 1,
0x0400_0300 => {
bus.io.postflg = @intToEnum(PostFlag, value & 1);
bus.io.postflg = @as(PostFlag, @enumFromInt(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 }),
@@ -246,7 +246,7 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
0x0400_0208 => bus.io.ime = value & 1 == 1,
0x0400_020A => {},
0x0400_0300 => {
bus.io.postflg = @intToEnum(PostFlag, value & 1);
bus.io.postflg = @as(PostFlag, @enumFromInt(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 }),
@@ -273,16 +273,16 @@ pub fn write(bus: *Bus, comptime T: type, address: u32, value: T) void {
0x0400_0140 => log.debug("Wrote 0x{X:0>2} to JOYCNT_L", .{value}),
// Interrupts
0x0400_0200, 0x0400_0201 => bus.io.ie.raw = setHalf(u16, bus.io.ie.raw, @truncate(u8, address), value),
0x0400_0200, 0x0400_0201 => bus.io.ie.raw = setHalf(u16, bus.io.ie.raw, @as(u8, @truncate(address)), value),
0x0400_0202 => bus.io.irq.raw &= ~@as(u16, value),
0x0400_0203 => bus.io.irq.raw &= ~@as(u16, value) << 8, // TODO: Is this good?
0x0400_0204, 0x0400_0205 => bus.io.waitcnt.set(setHalf(u16, @truncate(u16, bus.io.waitcnt.raw), @truncate(u8, address), value)),
0x0400_0204, 0x0400_0205 => bus.io.waitcnt.set(setHalf(u16, @as(u16, @truncate(bus.io.waitcnt.raw)), @as(u8, @truncate(address)), value)),
0x0400_0206, 0x0400_0207 => {},
0x0400_0208 => bus.io.ime = value & 1 == 1,
0x0400_0209 => {},
0x0400_020A, 0x0400_020B => {},
0x0400_0300 => bus.io.postflg = @intToEnum(PostFlag, value & 1),
0x0400_0300 => bus.io.postflg = @as(PostFlag, @enumFromInt(value & 1)),
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 }),

View File

@@ -19,7 +19,7 @@ pub fn create(sched: *Scheduler) TimerTuple {
}
pub fn read(comptime T: type, tim: *const TimerTuple, addr: u32) ?T {
const nybble_addr = @truncate(u4, addr);
const nybble_addr = @as(u4, @truncate(addr));
return switch (T) {
u32 => switch (nybble_addr) {
@@ -44,24 +44,24 @@ pub fn read(comptime T: type, tim: *const TimerTuple, addr: u32) ?T {
else => util.io.read.err(T, log, "unaligned {} read from 0x{X:0>8}", .{ T, addr }),
},
u8 => switch (nybble_addr) {
0x0, 0x1 => @truncate(T, tim.*[0].timcntL() >> getHalf(nybble_addr)),
0x2, 0x3 => @truncate(T, tim.*[0].cnt.raw >> getHalf(nybble_addr)),
0x0, 0x1 => @as(T, @truncate(tim.*[0].timcntL() >> getHalf(nybble_addr))),
0x2, 0x3 => @as(T, @truncate(tim.*[0].cnt.raw >> getHalf(nybble_addr))),
0x4, 0x5 => @truncate(T, tim.*[1].timcntL() >> getHalf(nybble_addr)),
0x6, 0x7 => @truncate(T, tim.*[1].cnt.raw >> getHalf(nybble_addr)),
0x4, 0x5 => @as(T, @truncate(tim.*[1].timcntL() >> getHalf(nybble_addr))),
0x6, 0x7 => @as(T, @truncate(tim.*[1].cnt.raw >> getHalf(nybble_addr))),
0x8, 0x9 => @truncate(T, tim.*[2].timcntL() >> getHalf(nybble_addr)),
0xA, 0xB => @truncate(T, tim.*[2].cnt.raw >> getHalf(nybble_addr)),
0x8, 0x9 => @as(T, @truncate(tim.*[2].timcntL() >> getHalf(nybble_addr))),
0xA, 0xB => @as(T, @truncate(tim.*[2].cnt.raw >> getHalf(nybble_addr))),
0xC, 0xD => @truncate(T, tim.*[3].timcntL() >> getHalf(nybble_addr)),
0xE, 0xF => @truncate(T, tim.*[3].cnt.raw >> getHalf(nybble_addr)),
0xC, 0xD => @as(T, @truncate(tim.*[3].timcntL() >> getHalf(nybble_addr))),
0xE, 0xF => @as(T, @truncate(tim.*[3].cnt.raw >> getHalf(nybble_addr))),
},
else => @compileError("TIM: Unsupported read width"),
};
}
pub fn write(comptime T: type, tim: *TimerTuple, addr: u32, value: T) void {
const nybble_addr = @truncate(u4, addr);
const nybble_addr = @as(u4, @truncate(addr));
return switch (T) {
u32 => switch (nybble_addr) {
@@ -141,7 +141,7 @@ fn Timer(comptime id: u2) type {
pub fn timcntL(self: *const Self) u16 {
if (self.cnt.cascade.read() or !self.cnt.enabled.read()) return self._counter;
return self._counter +% @truncate(u16, (self.sched.now() - self._start_timestamp) / self.frequency());
return self._counter +% @as(u16, @truncate((self.sched.now() - self._start_timestamp) / self.frequency()));
}
/// TIMCNT_L Setter
@@ -151,8 +151,8 @@ fn Timer(comptime id: u2) type {
/// TIMCNT_L & TIMCNT_H
pub fn setTimcnt(self: *Self, word: u32) void {
self.setTimcntL(@truncate(u16, word));
self.setTimcntH(@truncate(u16, word >> 16));
self.setTimcntL(@as(u16, @truncate(word)));
self.setTimcntH(@as(u16, @truncate(word >> 16)));
}
/// TIMCNT_H
@@ -167,7 +167,7 @@ fn Timer(comptime id: u2) type {
self.sched.removeScheduledEvent(.{ .TimerOverflow = id });
// Counter should hold the value it stopped at meaning we have to calculate it now
self._counter +%= @truncate(u16, (self.sched.now() - self._start_timestamp) / self.frequency());
self._counter +%= @as(u16, @truncate((self.sched.now() - self._start_timestamp) / self.frequency()));
}
// the timer has always been enabled, but the cascade bit which was blocking the timer has been unset
@@ -194,7 +194,7 @@ fn Timer(comptime id: u2) type {
pub fn onTimerExpire(self: *Self, cpu: *Arm7tdmi, late: u64) void {
// Fire IRQ if enabled
const bus_ptr = @ptrCast(*Bus, @alignCast(@alignOf(Bus), cpu.bus.ptr));
const bus_ptr: *Bus = @ptrCast(@alignCast(cpu.bus.ptr));
const io = &bus_ptr.io;