// SPDX-FileCopyrightText: 2024 Himbeer // // SPDX-License-Identifier: AGPL-3.0-or-later const std = @import("std"); const interrupts = @import("interrupts.zig"); const paging = @import("paging.zig"); pub const Privilege = enum(u1) { user, supervisor, }; pub const ExtensionState = enum(u2) { off, initial, clean, dirty, }; pub const Xlen = enum(u2) { rv32 = 1, rv64, rv128, }; pub const Sstatus = packed struct(usize) { user_interrupt_enable: u1, supervisor_interrupt_enable: u1, reserved0: u2, user_prior_interrupt_enable: u1, supervisor_prior_interrupt_enable: u1, reserved1: u2, previous_privilege: Privilege, reserved2: u4, floating_point_state: ExtensionState, user_extension_state: ExtensionState, reserved3: u1, supervisor_user_memory_access: u1, make_executable_readable: u1, reserved4: u12, user_xlen: Xlen, reserved5: u29, need_state_saving: u1, // Read-only. }; pub const SbiRet = struct { err: isize, val: isize, }; pub fn ecall(ext_id: usize, fn_id: usize, a0: usize, a1: usize, a2: usize) SbiRet { var ret = SbiRet{ .err = 0, .val = 0 }; asm volatile ( \\ ecall \\ sw a0, 0(%[err]) \\ sw a1, 0(%[val]) : : [err] "r" (&ret.err), [val] "r" (&ret.val), [eid] "{a7}" (ext_id), [fid] "{a6}" (fn_id), [a0] "{a0}" (a0), [a1] "{a1}" (a1), [a2] "{a2}" (a2), ); return ret; } pub fn stackPointer() usize { return asm volatile ("" : [value] "={sp}" (-> usize), ); } pub const satp = Csr(paging.Satp, "satp"); pub const sstatus = Csr(Sstatus, "sstatus"); pub const sie = Csr(interrupts.Enable, "sie"); pub const sip = Csr(interrupts.Enable, "sip"); pub const sscratch = Csr(usize, "sscratch"); pub const sepc = Csr(usize, "sepc"); pub const stval = Csr(usize, "stval"); pub const time = Csr(usize, "time"); pub fn Csr(comptime T: type, csr: []const u8) type { if (csr.len > 8) @compileError("CSR name length exceeds 8 characters"); return struct { pub inline fn read() T { comptime var buf = [_]u8{0} ** 23; const bits = asm volatile (std.fmt.bufPrint(buf[0..], "csrr %[bits], {s}", .{csr}) catch unreachable : [bits] "=r" (-> usize), ); return @bitCast(bits); } pub inline fn write(value: T) void { const bits: usize = @bitCast(value); comptime var buf = [_]u8{0} ** 23; asm volatile (std.fmt.bufPrint(buf[0..], "csrw {s}, %[bits]", .{csr}) catch unreachable : : [bits] "r" (bits), ); } }; }