// SPDX-FileCopyrightText: 2024 Himbeer // // SPDX-License-Identifier: AGPL-3.0-or-later const std = @import("std"); pub const max_args = 6; const Result = struct { value: usize, error_code: usize, }; const SyscallError = error{Kernel}; fn ecall(number: usize, args: anytype) Result { comptime var registers = [max_args]usize{0}; inline for (args, 0..) |arg, i| { if (i >= max_args) @compileError("Too many arguments to system call"); registers[i] = @bitCast(arg); } var result: Result = undefined; asm volatile ( \\ ecall \\ sw a0, 0(%[value]) \\ sw a1, 0(%[error_code]) : : [value] "r" (&result.value), [error_code] "r" (&result.error_code), [a0] "{a0}" (registers[0]), [a1] "{a1}" (registers[1]), [a2] "{a2}" (registers[2]), [a3] "{a3}" (registers[3]), [a4] "{a4}" (registers[4]), [a5] "{a5}" (registers[5]), [number] "{a7}" (number), ); return result; } pub fn errorName(code: u16, buffer: []u8) !usize { const result = ecall(100000, .{ code, buffer.ptr, buffer.len, }); if (result.error_code != 0) return SyscallError.Kernel; return result.value; } pub fn consoleWrite(bytes: []const u8) !usize { const result = ecall(100001, .{ bytes.ptr, bytes.len }); if (result.error_code != 0) return SyscallError.Kernel; return result.value; } pub fn launch(bytes: []align(@alignOf(std.elf.Elf64_Ehdr)) const u8) !usize { const result = ecall(100002, .{ bytes.ptr, bytes.len }); if (result.error_code != 0) return SyscallError.Kernel; return result.value; } pub fn end() noreturn { ecall(100003, .{}); } pub fn terminate(pid: u16, thread: usize) !void { const result = ecall(100004, .{ pid, thread }); if (result.error_code != 0) return SyscallError.Kernel; }