diff --git a/modules/riscv32-common/src/riscv32_common.zig b/modules/riscv32-common/src/riscv32_common.zig index 72a1da7be..dad2cdff9 100644 --- a/modules/riscv32-common/src/riscv32_common.zig +++ b/modules/riscv32-common/src/riscv32_common.zig @@ -140,9 +140,38 @@ pub const csr = struct { pub const mconfigptr = Csr(0xF15, u32); pub const mstatus = Csr(0x300, packed struct { - reserved0: u3, - mie: u1, - reserved1: u28, + pub const XS = enum(u2) { + /// Extension unit status + off = 0b00, + initial = 0b01, + clean = 0b10, + dirty = 0b11, + }; + pub const FS = XS; + pub const VS = XS; + pub const MPP = enum(u2) { + user = 0b00, + supervisor = 0b01, + hypervisor = 0b10, + machine = 0b11, + }; + + reserved0: u1 = 0, + sie: u1 = 0, + reserved2: u1 = 0, + mie: u1 = 0, + reserved4: u1 = 0, + spie: u1 = 0, + ube: u1 = 0, + mpie: u1 = 0, + spp: u1 = 0, + vs: VS = @enumFromInt(0), + mpp: MPP = @enumFromInt(0), + fs: FS = @enumFromInt(0), + xs: XS = @enumFromInt(0), + mprv: u1 = 0, + reserved18: u13 = 0, + sd: u1 = 0, }); pub const misa = Csr(0x301, u32); pub const medeleg = Csr(0x302, u32); @@ -154,8 +183,8 @@ pub const csr = struct { vectored = 0b01, }; - mode: Mode, - base: u30, + mode: Mode = .direct, + base: u30 = 0, }); pub const mcounteren = Csr(0x306, u32); pub const mstatush = Csr(0x310, u32); @@ -388,6 +417,15 @@ pub const csr = struct { return struct { const Self = @This(); + /// Convert from basic types to CSR packed struct + pub inline fn from_val(val: anytype) T { + switch (@typeInfo(@TypeOf(val))) { + .comptime_int => return @bitCast(@as(u32, val)), + .int => return @bitCast(val), + else => @compileError("unsupported type"), + } + } + pub inline fn read_raw() u32 { return asm volatile ("csrr %[value], " ++ ident : [value] "=r" (-> u32), @@ -398,11 +436,18 @@ pub const csr = struct { return @bitCast(read_raw()); } - pub inline fn write_raw(value: u32) void { - asm volatile ("csrw " ++ ident ++ ", %[value]" - : - : [value] "r" (value), - ); + pub inline fn write_raw(bits: u32) void { + if (is_comptime(bits) and comptime (bits & std.math.maxInt(u5) == bits)) { + asm volatile ("csrwi " ++ ident ++ ", %[bits]" + : + : [bits] "i" (bits), + ); + } else { + asm volatile ("csrw " ++ ident ++ ", %[bits]" + : + : [bits] "r" (bits), + ); + } } pub inline fn write(value: T) void { @@ -424,25 +469,39 @@ pub const csr = struct { } pub inline fn set_raw(bits: u32) void { - asm volatile ("csrs " ++ ident ++ ", %[bits]" - : - : [bits] "r" (bits), - ); + if (is_comptime(bits) and comptime (bits & std.math.maxInt(u5) == bits)) { + asm volatile ("csrsi " ++ ident ++ ", %[bits]" + : + : [bits] "i" (bits), + ); + } else { + asm volatile ("csrs " ++ ident ++ ", %[bits]" + : + : [bits] "r" (bits), + ); + } } - pub inline fn set(fields: anytype) void { - set_raw(get_bits(fields)); + pub inline fn set(fields: T) void { + set_raw(@bitCast(fields)); } pub inline fn clear_raw(bits: u32) void { - asm volatile ("csrc " ++ ident ++ ", %[bits]" - : - : [bits] "r" (bits), - ); + if (is_comptime(bits) and comptime (bits & std.math.maxInt(u5) == bits)) { + asm volatile ("csrci " ++ ident ++ ", %[bits]" + : + : [bits] "i" (bits), + ); + } else { + asm volatile ("csrc " ++ ident ++ ", %[bits]" + : + : [bits] "r" (bits), + ); + } } - pub inline fn clear(fields: anytype) void { - clear_raw(get_bits(fields)); + pub inline fn clear(fields: T) void { + clear_raw(@bitCast(fields)); } pub inline fn read_set_raw(bits: u32) u32 { @@ -480,6 +539,17 @@ pub const csr = struct { else => @compileError("unsupported type"), }; } + + inline fn is_comptime(x: anytype) bool { + // Voodoo to determine whether x is comptime known + return comptime check: { + // For anonymous tuple types, + // if the value of a field is comptime known, + // then the corresponding field in that tuple's type is comptime. + const field = @typeInfo(@TypeOf(.{x})).@"struct".fields[0]; + break :check field.is_comptime; + }; + } }; } }; diff --git a/port/raspberrypi/rp2xxx/src/cpus/hazard3.zig b/port/raspberrypi/rp2xxx/src/cpus/hazard3.zig index 8f29f36b1..97dbf3012 100644 --- a/port/raspberrypi/rp2xxx/src/cpus/hazard3.zig +++ b/port/raspberrypi/rp2xxx/src/cpus/hazard3.zig @@ -447,31 +447,31 @@ pub const csr = struct { pub const dpc = riscv32_common.csr.dpc; pub const meiea = Csr(0xbe0, packed struct { - index: u5, - reserved0: u11, - window: u16, + index: u5 = 0, + reserved0: u11 = 0, + window: u16 = 0, }); pub const meipa = Csr(0xbe1, packed struct { - index: u5, - reserved0: u11, - window: u16, + index: u5 = 0, + reserved0: u11 = 0, + window: u16 = 0, }); pub const meifa = Csr(0xbe2, packed struct { - index: u5, - reserved0: u11, - window: u16, + index: u5 = 0, + reserved0: u11 = 0, + window: u16 = 0, }); pub const meipra = Csr(0xbe3, packed struct { - index: u5, - reserved0: u11, - window: u16, + index: u5 = 0, + reserved0: u11 = 0, + window: u16 = 0, }); pub const meinext = Csr(0xbe4, packed struct { - update: u1, - reserved0: u1, - irq: u9, - reserved1: u20, - noirq: u1, + update: u1 = 0, + reserved0: u1 = 0, + irq: u9 = 0, + reserved1: u20 = 0, + noirq: u1 = 0, }); pub const meicontext = Csr(0xbe5, u32); diff --git a/port/wch/ch32v/src/cpus/main.zig b/port/wch/ch32v/src/cpus/main.zig index db931efbf..dd21a13a2 100644 --- a/port/wch/ch32v/src/cpus/main.zig +++ b/port/wch/ch32v/src/cpus/main.zig @@ -435,7 +435,7 @@ pub const csr = struct { /// Machine Mode Status Register pub const mstatus = Csr(0x300, packed struct(u32) { - pub const Fs = enum(u2) { + pub const FS = enum(u2) { /// Floating-point unit status off = 0b00, initial = 0b01, @@ -446,11 +446,11 @@ pub const csr = struct { /// [2:0] Reserved reserved0: u3 = 0, /// [3] Machine mode interrupt enable - mie: u1, + mie: u1 = 0, /// [6:4] Reserved reserved4: u3 = 0, /// [7] Interrupt enable state before entering interrupt - mpie: u1, + mpie: u1 = 0, /// [10:8] Reserved reserved8: u3 = 0, /// [12:11] Privileged mode before entering break @@ -458,7 +458,7 @@ pub const csr = struct { /// [14:13] Floating-point unit status /// Valid only for WCH-V4F /// NOTE: reserved on other chips - fs: Fs = .off, + fs: FS = .off, /// [31:15] Reserved reserved15: u17 = 0, }); @@ -473,16 +473,16 @@ pub const csr = struct { /// Interrupt or exception entry address mode selection. /// 0: Use of the uniform entry address. /// 1: Address offset based on interrupt number *4. - mode0: u1, + mode0: u1 = 0, /// [1] Mode 1 /// Interrupt vector table identifies patterns. /// 0: Identification by jump instruction, /// limited range, support for non-jump 0 instructions. /// 1: Identify by absolute address, support /// full range, but must jump. - mode1: u1, + mode1: u1 = 0, /// [31:2] Base address of the interrupt vector table - base: u30, + base: u30 = 0, }); pub const mscratch = riscv32_common.csr.mscratch;