commit ae01224987871318eb43bb22ede4b85ea1134265
parent f477517306c3a8bb1adfdcadf2b369fcf16bec95
Author: Sylvia Ivory <git@sivory.net>
Date: Fri, 23 Jan 2026 20:47:46 -0800
Cleanup PSR handling
Diffstat:
6 files changed, 130 insertions(+), 80 deletions(-)
diff --git a/.rgignore b/.rgignore
@@ -0,0 +1 @@
+/submodules
diff --git a/pi/cpsr.zig b/pi/cpsr.zig
@@ -1,66 +0,0 @@
-pub const Mode = enum(u5) {
- User = 0b10000,
- FIQ = 0b10001,
- IRQ = 0b10010,
- Supervisor = 0b10011,
- Abort = 0b10111,
- Undefined = 0b11011,
- System = 0b11111,
-};
-
-pub const CPSR = packed struct(u32) {
- mode: Mode,
- t: bool,
- f: bool,
- i: bool,
- a: bool,
- e: bool,
- _reserved_10_15: u6,
- ge: u4,
- _reserved_20_23: u4,
- j: bool,
- res: u2,
- q: bool,
- v: bool,
- c: bool,
- z: bool,
- n: bool,
-};
-
-pub inline fn get() CPSR {
- return asm volatile ("MRS %[result], cpsr"
- : [result] "=r" (-> 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_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;
- set(cpsr);
-}
-
-pub inline fn disable_interrupts() void {
- var cpsr = get();
- cpsr.i = false;
- set(cpsr);
-}
diff --git a/pi/interrupts.zig b/pi/interrupts.zig
@@ -1,4 +1,3 @@
-const cpsr = @import("./cpsr.zig");
const mem = @import("./mem.zig");
const BASE_ADDRESS: usize = mem.BASE_ADDRESS + 0xB200;
diff --git a/pi/psr.zig b/pi/psr.zig
@@ -0,0 +1,119 @@
+/// # Program Status Register
+/// Reference: ARM1176JZF-S Technical Reference Manual - A2.5
+///
+/// Contains condition code flags, interrupt disable bits, processor mode, and
+/// other status control
+pub const PSR = packed struct(u32) {
+ /// # The mode bits
+ /// Reference: ARM1176JZF-S Technical Reference Manual - A2.5.7
+ ///
+ /// Determines the mode in which the processor operates
+ pub const Mode = enum(u5) {
+ /// Accessible Registers: PC, R14 to R0, CPSR
+ User = 0b10000,
+ /// Accessible Registers: PC, R14_FIQ to R8_FIQ, R7 to R0, CPSR, SPSR_FIQ
+ FIQ = 0b10001,
+ /// Accessible Registers: PC, R14_IRQ, R13_IRQ, R12 to R0, CPSR, SPSR_IRQ
+ IRQ = 0b10010,
+ /// Accessible Registers: PC, R14_SVC, R13_SVC, R12 to R0, CPSR, SPSR_SVC
+ Supervisor = 0b10011,
+ /// Accessible Registers: PC, R14_ABT, R13_ABT, R12 to R0, CPSR, SPSR_ABRT
+ Abort = 0b10111,
+ /// Accessible Registers: PC, R14_UND, R13_UND, R12 to R0, CPSR, SPSR_UND
+ Undefined = 0b11011,
+ /// Accessible Registers: PC, R14 to R0, CPSR
+ System = 0b11111,
+ };
+
+ /// ## Mode bits
+ /// Determines the mode in which the processor operates
+ mode: Mode,
+ /// Thumb ISA
+ t: bool,
+ /// ## Interrupt Disable Flag: F
+ /// Disables FIQ interrupts when set
+ f: bool,
+ /// ## Interrupt Disable Flag: I
+ /// Disables IRQ interrupts when set
+ i: bool,
+ /// ## Interrupt Disable Flag: A
+ /// Disables imprecise data aborts when set
+ a: bool,
+ /// ## E Flag
+ /// Endianness control for data handling (ignored for fetches)
+ e: bool,
+ _reserved_10_15: u6,
+ /// SIMD Greater than or Equal flag
+ ge: u4,
+ _reserved_20_23: u4,
+ /// Jazelle ISA
+ j: bool,
+ /// Reserved
+ _reserved_25_26: u2,
+ /// ## Q Flag
+ /// Set to 1 if overflow/saturation occurred
+ q: bool,
+ /// ## Condition Code Flag: V (overflow)
+ /// Set to 1 for signed overflow (add/sub only)
+ v: bool,
+ /// ## Condition Code Flag: C (carry)
+ /// Set to:
+ /// - 1 for carry if addition
+ /// - 1 for borrow if subtraction
+ /// - last bit shifted out if shift
+ /// - otherwise, left unchanged (usually)
+ c: bool,
+ /// ## Condition Code Flag: Z (zero)
+ /// Set to 1 if the result of the instruction is 0.
+ z: bool,
+ /// ## Condition Code Flag: N (sign)
+ /// Set to bit 31st bit of the result of the instruction.
+ n: bool,
+
+ /// Get the CPSR
+ pub inline fn get_c() @This() {
+ return asm volatile ("MRS %[result], cpsr"
+ : [result] "=r" (-> @This()),
+ );
+ }
+
+ /// Get the SPSR
+ pub inline fn get_s() @This() {
+ return asm volatile ("MRS %[result], spsr"
+ : [result] "=r" (-> @This()),
+ );
+ }
+
+ /// Set the CPSR
+ pub inline fn set_c(cpsr: *const @This()) void {
+ return asm volatile ("MSR cpsr_cxsf, %[value]"
+ :
+ : [value] "r" (@as(u32, @bitCast(cpsr.*))),
+ : .{ .cpsr = true });
+ }
+
+ /// Set the SPSR
+ pub inline fn set_s(spsr: *const @This()) PSR {
+ return asm volatile ("MRS spsr_cxsf, %[value]"
+ :
+ : [value] "r" (@as(u32, @bitCast(spsr.*))),
+ : .{ .cpsr = true });
+ }
+
+ /// Switch the current mode and return the old CPSR
+ pub inline fn switch_current_mode(mode: Mode) PSR {
+ const cpsr = get_c();
+ var new_cpsr = cpsr;
+
+ new_cpsr.mode = mode;
+ new_cpsr.set_c();
+
+ return cpsr;
+ }
+
+ pub inline fn call_with_mode(mode: Mode, f: *const fn () void) void {
+ const old_mode = switch_current_mode(mode);
+ f();
+ switch_current_mode(old_mode);
+ }
+};
diff --git a/pi/root.zig b/pi/root.zig
@@ -1,5 +1,5 @@
pub const interrupts = @import("./interrupts.zig");
-pub const cpsr = @import("./cpsr.zig");
+pub const PSR = @import("./psr.zig").PSR;
pub const mem = @import("./mem.zig");
pub inline fn cycle_counter_init() void {
@@ -36,25 +36,20 @@ var irq_stack: [32]usize align(8) = .{0} ** 32;
var fiq_stack: [32]usize align(8) = .{0} ** 32;
pub export fn setup_stacks() void {
- const original_cpsr = cpsr.get();
- var new_cpsr = original_cpsr;
+ const original_cpsr = PSR.get_c();
- new_cpsr.mode = .Undefined;
- cpsr.set(new_cpsr);
+ _ = PSR.switch_current_mode(.Undefined);
set_sp(@ptrFromInt(@intFromPtr(&abort_stack) + (abort_stack.len * @sizeOf(usize))));
- new_cpsr.mode = .Abort;
- cpsr.set(new_cpsr);
+ _ = PSR.switch_current_mode(.Abort);
set_sp(@ptrFromInt(@intFromPtr(&abort_stack) + (abort_stack.len * @sizeOf(usize))));
- new_cpsr.mode = .IRQ;
- cpsr.set(new_cpsr);
+ _ = PSR.switch_current_mode(.IRQ);
set_sp(@ptrFromInt(@intFromPtr(&irq_stack) + (irq_stack.len * @sizeOf(usize))));
- new_cpsr.mode = .FIQ;
- cpsr.set(new_cpsr);
+ _ = PSR.switch_current_mode(.FIQ);
set_sp(@ptrFromInt(@intFromPtr(&fiq_stack) + (fiq_stack.len * @sizeOf(usize))));
// Restore
- cpsr.set(original_cpsr);
+ original_cpsr.set_c();
}
diff --git a/src/main.zig b/src/main.zig
@@ -1 +1,3 @@
-fn main() !void {}
+export fn syscall_handler() void {}
+
+pub fn main() !void {}