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 };