commit a0e84bf32460b7868e293d9aa2daf5a9879b3cd3
parent ab2d3ee79f760a36c0bb12ca2ceb8b44c01d84a4
Author: Sylvia Ivory <git@sivory.net>
Date: Fri, 23 Jan 2026 20:17:55 -0800
Add syscall-2 (new root needed)
Diffstat:
4 files changed, 99 insertions(+), 6 deletions(-)
diff --git a/pi/cpsr.zig b/pi/cpsr.zig
@@ -33,13 +33,26 @@ pub inline fn get() CPSR {
);
}
+pub inline fn get_s() CPSR {
+ return asm volatile ("MRS %[result], spsr"
+ : [result] "=r" (-> CPSR),
+ );
+}
+
pub inline fn set(cpsr: CPSR) void {
- return asm volatile ("MSR cpsr_c, %[value]"
+ return asm volatile ("MSR cpsr_cxsf, %[value]"
:
: [value] "r" (@as(u32, @bitCast(cpsr))),
: .{ .cpsr = true });
}
+pub inline fn set_s(cpsr: CPSR) CPSR {
+ return asm volatile ("MRS spsr_cxsf, %[value]"
+ :
+ : [value] "r" (cpsr),
+ : .{ .cpsr = true });
+}
+
pub inline fn enable_interrupts() void {
var cpsr = get();
cpsr.i = true;
diff --git a/pi/interrupts.zig b/pi/interrupts.zig
@@ -102,13 +102,13 @@ comptime {
\\ .global software_interrupt;
\\ .type software_interrupt, %function;
\\ software_interrupt:
- \\ push {r0-r2, lr}
- \\ mov r1, r0
+ \\ push {r0-r12, lr}
\\ sub lr, lr, #4
+ \\ mov r1, r0
\\ mov r0, lr
\\ bl syscall_handler
- \\ pop {r0-r2, lr}
- \\ subs pc, lr, #0
+ \\ pop {r0-r12, lr}
+ \\ movs pc, lr
);
}
extern fn software_interrupt() void;
diff --git a/src/labs/4-syscall-2.zig b/src/labs/4-syscall-2.zig
@@ -0,0 +1,80 @@
+const pi = @import("pi");
+
+const uart = @import("devices/mini-uart.zig");
+
+comptime {
+ asm (
+ \\ .global syscall_hello;
+ \\ .type syscall_hello, %function;
+ \\ syscall_hello:
+ \\ push {lr}
+ \\ swi 1
+ \\ pop {lr}
+ \\ bx lr
+ \\
+ \\ .global syscall_illegal;
+ \\ .type syscall_illegal, %function;
+ \\ syscall_illegal:
+ \\ push {lr}
+ \\ swi 2
+ \\ pop {lr}
+ \\ bx lr
+ );
+}
+
+extern fn syscall_hello(msg: *const u8) i32;
+extern fn syscall_illegal() i32;
+
+const Syscall = packed struct(u32) {
+ num: u24,
+ _: u4,
+ cond: u4,
+};
+
+export fn syscall_handler(pc: u32, r0: u32) i32 {
+ const syscall: Syscall = @bitCast(pi.mem.get_u32(@ptrFromInt(pc)));
+
+ uart.writer.print("instruction=0x{X}, number={d}\n", .{ @as(u32, @bitCast(syscall)), syscall.num }) catch {};
+
+ const spsr = pi.cpsr.get_s();
+ uart.writer.print("saved spsr mode = {t}\n", .{spsr.mode}) catch {};
+
+ switch (syscall.num) {
+ 1 => {
+ uart.write_slice("syscall: ");
+ const str: [*]const u8 = @ptrFromInt(r0);
+ var i: usize = 0;
+
+ while (str[i] != 0) {
+ uart.write_byte(str[i]);
+ i += 1;
+ }
+
+ syscall_return(0);
+ return 0;
+ },
+ else => {
+ uart.writer.print("illegal system call: {d}!\n", .{syscall.num}) catch {};
+ syscall_return(-1);
+ return -1;
+ },
+ }
+}
+
+pub fn main() !void {
+ // Switch to user
+ var cpsr = pi.cpsr.get();
+ cpsr.mode = .User;
+ pi.cpsr.set(cpsr);
+
+ try uart.writer.print("current stack pointer = 0x{x}\n", .{pi.get_sp()});
+ try uart.writer.print("current cpsr mode = {t}\n", .{cpsr.mode});
+
+ try uart.writer.print("running syscall hello\n", .{});
+ const res_hello = syscall_hello(@ptrCast("hello world!\n"));
+ try uart.writer.print("result of calling syscall: {d}\n", .{res_hello});
+
+ try uart.writer.print("running illegal call\n", .{});
+ const res_illegal = syscall_illegal();
+ try uart.writer.print("result of illegal syscall: {d}\n", .{res_illegal});
+}
diff --git a/src/main.zig b/src/main.zig
@@ -1 +1 @@
-pub fn main() !void {}
+fn main() !void {}