sylveos

Toy Operating System
Log | Files | Refs

psr.zig (3711B)


      1 /// # Program Status Register
      2 /// Reference: ARM1176JZF-S Technical Reference Manual - A2.5
      3 ///
      4 /// Contains condition code flags, interrupt disable bits, processor mode, and
      5 /// other status control
      6 pub const PSR = packed struct(u32) {
      7     /// # The mode bits
      8     /// Reference: ARM1176JZF-S Technical Reference Manual - A2.5.7
      9     ///
     10     /// Determines the mode in which the processor operates
     11     pub const Mode = enum(u5) {
     12         /// Accessible Registers: PC, R14 to R0, CPSR
     13         User = 0b10000,
     14         /// Accessible Registers: PC, R14_FIQ to R8_FIQ, R7 to R0, CPSR, SPSR_FIQ
     15         FIQ = 0b10001,
     16         /// Accessible Registers: PC, R14_IRQ, R13_IRQ, R12 to R0, CPSR, SPSR_IRQ
     17         IRQ = 0b10010,
     18         /// Accessible Registers: PC, R14_SVC, R13_SVC, R12 to R0, CPSR, SPSR_SVC
     19         Supervisor = 0b10011,
     20         /// Accessible Registers: PC, R14_ABT, R13_ABT, R12 to R0, CPSR, SPSR_ABRT
     21         Abort = 0b10111,
     22         /// Accessible Registers: PC, R14_UND, R13_UND, R12 to R0, CPSR, SPSR_UND
     23         Undefined = 0b11011,
     24         /// Accessible Registers: PC, R14 to R0, CPSR
     25         System = 0b11111,
     26     };
     27 
     28     /// ## Mode bits
     29     /// Determines the mode in which the processor operates
     30     mode: Mode,
     31     /// Thumb ISA
     32     t: bool,
     33     /// ## Interrupt Disable Flag: F
     34     /// Disables FIQ interrupts when set
     35     f: bool,
     36     /// ## Interrupt Disable Flag: I
     37     /// Disables IRQ interrupts when set
     38     i: bool,
     39     /// ## Interrupt Disable Flag: A
     40     /// Disables imprecise data aborts when set
     41     a: bool,
     42     /// ## E Flag
     43     /// Endianness control for data handling (ignored for fetches)
     44     e: bool,
     45     _reserved_10_15: u6,
     46     /// SIMD Greater than or Equal flag
     47     ge: u4,
     48     _reserved_20_23: u4,
     49     /// Jazelle ISA
     50     j: bool,
     51     /// Reserved
     52     _reserved_25_26: u2,
     53     /// ## Q Flag
     54     /// Set to 1 if overflow/saturation occurred
     55     q: bool,
     56     /// ## Condition Code Flag: V (overflow)
     57     /// Set to 1 for signed overflow (add/sub only)
     58     v: bool,
     59     /// ## Condition Code Flag: C (carry)
     60     /// Set to:
     61     /// - 1 for carry if addition
     62     /// - 1 for borrow if subtraction
     63     /// - last bit shifted out if shift
     64     /// - otherwise, left unchanged (usually)
     65     c: bool,
     66     /// ## Condition Code Flag: Z (zero)
     67     /// Set to 1 if the result of the instruction is 0.
     68     z: bool,
     69     /// ## Condition Code Flag: N (sign)
     70     /// Set to bit 31st bit of the result of the instruction.
     71     n: bool,
     72 
     73     /// Get the CPSR
     74     pub inline fn get_c() @This() {
     75         return asm volatile ("MRS %[result], cpsr"
     76             : [result] "=r" (-> @This()),
     77         );
     78     }
     79 
     80     /// Get the SPSR
     81     pub inline fn get_s() @This() {
     82         return asm volatile ("MRS %[result], spsr"
     83             : [result] "=r" (-> @This()),
     84         );
     85     }
     86 
     87     /// Set the CPSR
     88     pub inline fn set_c(cpsr: *const @This()) void {
     89         asm volatile ("MSR cpsr_cxsf, %[value]"
     90             :
     91             : [value] "r" (@as(u32, @bitCast(cpsr.*))),
     92             : .{ .cpsr = true });
     93     }
     94 
     95     /// Set the SPSR
     96     pub inline fn set_s(spsr: *const @This()) void {
     97         asm volatile ("MSR spsr_cxsf, %[value]"
     98             :
     99             : [value] "r" (@as(u32, @bitCast(spsr.*))),
    100             : .{ .cpsr = true });
    101     }
    102 
    103     /// Switch the current mode and return the old CPSR
    104     pub inline fn switch_current_mode(mode: Mode) PSR {
    105         const cpsr = get_c();
    106         var new_cpsr = cpsr;
    107 
    108         new_cpsr.mode = mode;
    109         new_cpsr.set_c();
    110 
    111         return cpsr;
    112     }
    113 
    114     pub inline fn call_with_mode(mode: Mode, f: *const fn () void) void {
    115         const old_mode = switch_current_mode(mode);
    116         f();
    117         switch_current_mode(old_mode);
    118     }
    119 };