commit 6a121abe685d378dd68813044283f763bdbc3107
parent df5c42c175e426c3425088bb629739c8c00916db
Author: Sylvia Ivory <git@sivory.net>
Date: Tue, 10 Feb 2026 19:14:08 -0800
Clobber all registers in interrupts
Diffstat:
| M | pi/interrupts.zig | | | 64 | +++++++++++++++++++++++++++++++++------------------------------- |
1 file changed, 33 insertions(+), 31 deletions(-)
diff --git a/pi/interrupts.zig b/pi/interrupts.zig
@@ -97,16 +97,9 @@ fn empty(lr: u32) void {
_ = lr;
}
-// TODO; r1-r6
-fn empty_swi(n: u32, r0: u32) callconv(.c) i32 {
- _ = n;
- _ = r0;
- return -1;
-}
-
var reset_handler: *const fn (u32) void = empty;
var undefined_instruction_handler: *const fn (u32) void = empty;
-export var software_interrupt_handler: *const fn (u32, u32) callconv(.c) i32 = empty_swi;
+var software_interrupt_handler: *const fn (u32) void = empty;
var prefetch_abort_handler: *const fn (u32) void = empty;
var data_abort_handler: *const fn (u32) void = empty;
var interrupt_handler: *const fn (u32) void = empty;
@@ -118,43 +111,54 @@ inline fn get_lr() u32 {
);
}
+inline fn clobber_all() void {
+ asm volatile ("" ::: .{
+ .r0 = true,
+ .r1 = true,
+ .r2 = true,
+ .r3 = true,
+ .r4 = true,
+ .r5 = true,
+ .r6 = true,
+ .r7 = true,
+ .r8 = true,
+ .r9 = true,
+ .r10 = true,
+ .r11 = true,
+ .r12 = true,
+ .r14 = true,
+ });
+}
+
export fn reset() callconv(.{ .arm_interrupt = .{ .type = .generic } }) void {
- reset_handler(0);
+ clobber_all();
+ reset_handler(get_lr() - 4);
}
export fn undefined_instruction() callconv(.{ .arm_interrupt = .{ .type = .undef } }) void {
+ clobber_all();
undefined_instruction_handler(get_lr() - 4);
}
+export fn software_interrupt() callconv(.{ .arm_interrupt = .{ .type = .swi } }) void {
+ clobber_all();
+ software_interrupt_handler(get_lr() - 4);
+}
export fn prefetch_abort() callconv(.{ .arm_interrupt = .{ .type = .abort } }) void {
+ clobber_all();
prefetch_abort_handler(get_lr() - 8);
}
export fn data_abort() callconv(.{ .arm_interrupt = .{ .type = .abort } }) void {
+ clobber_all();
data_abort_handler(get_lr() - 4);
}
export fn interrupt() callconv(.{ .arm_interrupt = .{ .type = .irq } }) void {
+ clobber_all();
interrupt_handler(get_lr() - 4);
}
export fn fast_interrupt() callconv(.{ .arm_interrupt = .{ .type = .fiq } }) void {
+ clobber_all();
fast_interrupt_handler(get_lr() - 4);
}
-// TODO; fix
-comptime {
- asm (
- \\ .global software_interrupt;
- \\ .type software_interrupt, %function;
- \\ software_interrupt:
- \\ push {r0-r12, lr}
- \\ sub lr, lr, #4
- \\ mov r1, r0
- \\ mov r0, lr
- \\ bl syscall_handler
- \\ pop {r0-r12, lr}
- \\ movs pc, lr
- );
-}
-extern fn software_interrupt() void;
-export fn syscall_handler() void {}
-
// https://leiradel.github.io/2019/02/09/Initialization.html
pub fn setup_exception_vector() void {
var exception_vector: usize = 0;
@@ -193,6 +197,7 @@ pub fn setup_exception_vector() void {
const ExceptionVector = enum {
Reset,
UndefinedInstruction,
+ SoftwareInterrupt,
PrefetchAbort,
DataAbort,
IRQ,
@@ -203,13 +208,10 @@ pub fn set_exception_handler(vector: ExceptionVector, handler: *const fn (u32) v
switch (vector) {
.Reset => reset_handler = handler,
.UndefinedInstruction => undefined_instruction_handler = handler,
+ .SoftwareInterrupt => software_interrupt_handler = handler,
.PrefetchAbort => prefetch_abort_handler = handler,
.DataAbort => data_abort_handler = handler,
.IRQ => interrupt_handler = handler,
.FIQ => fast_interrupt_handler = handler,
}
}
-
-pub fn set_software_interrupt(handler: *const fn (u32, u32) callconv(.c) i32) void {
- software_interrupt_handler = handler;
-}