sylveos

Toy Operating System
Log | Files | Refs

commit ae01224987871318eb43bb22ede4b85ea1134265
parent f477517306c3a8bb1adfdcadf2b369fcf16bec95
Author: Sylvia Ivory <git@sivory.net>
Date:   Fri, 23 Jan 2026 20:47:46 -0800

Cleanup PSR handling

Diffstat:
A.rgignore | 1+
Dpi/cpsr.zig | 66------------------------------------------------------------------
Mpi/interrupts.zig | 1-
Api/psr.zig | 119+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mpi/root.zig | 19+++++++------------
Msrc/main.zig | 4+++-
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 {}