// SPDX-FileCopyrightText: 2024 Himbeer // // SPDX-License-Identifier: AGPL-3.0-or-later const std = @import("std"); const paging = @import("paging.zig"); pub const SbiRet = struct { err: isize, val: isize, }; // # Arguments // // * ext_id: Extension ID // * fn_id: Function ID (within extension) // * a0: Argument 0 // * a1: Argument 1 // * a2: Argument 2 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 setSatp = setCsrFn(paging.Satp, "satp").?; pub const setSscratch = setCsrFn(usize, "sscratch").?; pub const setSepc = setCsrFn(usize, "sepc").?; pub fn setCsrFn(comptime T: type, csr: []const u8) ?fn (T) void { if (csr.len > 8) return null; return struct { fn setCsr(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), ); } }.setCsr; }