aboutsummaryrefslogtreecommitdiff
path: root/src/lib/instructions.zig
blob: 2ae53eca6e483859f5a9c01ebc02e104202f203e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// SPDX-FileCopyrightText: 2024 Himbeer <himbeer@disroot.org>
//
// 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) callconv(.Inline) void {
    if (csr.len > 8) return null;

    return struct {
        inline 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;
}