cortex_ar/register/
cpsr.rs

1//! Code for managing CPSR (*Current Program Status Register*)
2
3/// The current Processor Mode
4#[derive(Debug, PartialEq, Eq)]
5#[cfg_attr(feature = "defmt", derive(defmt::Format))]
6#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
7#[bitbybit::bitenum(u5, exhaustive = false)]
8pub enum ProcessorMode {
9    /// User Mode
10    Usr = 0b10000,
11    /// FIQ Mode
12    Fiq = 0b10001,
13    /// IRQ Mode
14    Irq = 0b10010,
15    /// Supervisor Mode
16    Svc = 0b10011,
17    /// Monitor Mode
18    Mon = 0b10110,
19    /// Abort Mode
20    Abt = 0b10111,
21    /// Hyp Mode
22    Hyp = 0b11010,
23    /// Undefined Mode
24    Und = 0b11011,
25    /// System Mode
26    Sys = 0b11111,
27}
28
29/// CPSR (*Current Program Status Register*)
30#[bitbybit::bitfield(u32)]
31#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
32pub struct Cpsr {
33    /// Negative Result from ALU
34    #[bits(31..=31, r)]
35    n: bool,
36    /// Zero Result from ALU
37    #[bits(30..=30, r)]
38    z: bool,
39    /// ALU operation Carry Out
40    #[bits(29..=29, r)]
41    c: bool,
42    /// ALU operation Overflow
43    #[bits(28..=28, r)]
44    v: bool,
45    /// Cumulative Saturation
46    #[bits(27..=27, r)]
47    q: bool,
48    /// Jazelle State
49    #[bits(24..=24, r)]
50    j: bool,
51    /// Endianness
52    #[bits(9..=9, rw)]
53    e: bool,
54    /// Asynchronous Aborts
55    #[bits(8..=8, rw)]
56    a: bool,
57    /// Interrupts Enabled
58    #[bits(7..=7, rw)]
59    i: bool,
60    /// Fast Interrupts Enabled
61    #[bits(6..=6, rw)]
62    f: bool,
63    /// Thumb state
64    #[bits(5..=5, rw)]
65    t: bool,
66    /// Processor Mode
67    #[bits(0..=4, rw)]
68    mode: Option<ProcessorMode>,
69}
70
71impl Cpsr {
72    /// Read CPSR (*Current Program Status Register*)
73    #[inline]
74    pub fn read() -> Self {
75        let r: u32;
76        // Safety: Reading this register has no side-effects and is atomic
77        #[cfg(target_arch = "arm")]
78        unsafe {
79            core::arch::asm!("mrs {}, CPSR", out(reg) r, options(nomem, nostack, preserves_flags));
80        }
81        #[cfg(not(target_arch = "arm"))]
82        {
83            r = 0;
84        }
85        Self::new_with_raw_value(r)
86    }
87
88    /// Write CPSR (*Current Program Status Register*)
89    ///
90    /// # Safety
91    ///
92    /// Changing the Program Status Register can affect whether interrupts are
93    /// enabled, whether we are executing Arm or Thumb instructions, or which
94    /// processor mode are in. You must be absolutely certain that the new CPSR
95    /// value is valid and appropriate for continued Rust code execution.
96    ///
97    /// You almost certainly want to follow this with an [ISB](crate::asm::isb)
98    /// instruction.
99    #[inline]
100    pub unsafe fn write(_value: Self) {
101        // Safety: This is risky, but we're in an unsafe function
102        #[cfg(target_arch = "arm")]
103        unsafe {
104            core::arch::asm!("msr CPSR, {}", in(reg) _value.raw_value());
105        }
106    }
107
108    /// Modify SCTLR (*System Control Register*)
109    ///
110    /// # Safety
111    ///
112    /// See docs for [Self::write].
113    #[inline]
114    pub unsafe fn modify<F>(f: F)
115    where
116        F: FnOnce(&mut Self),
117    {
118        let mut value = Self::read();
119        f(&mut value);
120        unsafe {
121            Self::write(value);
122        }
123    }
124}
125
126impl core::fmt::Debug for Cpsr {
127    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
128        write!(
129            f,
130            "CPSR {{ N={} Z={} C={} V={} Q={} J={} E={} A={} I={} F={} T={} MODE={:?} }}",
131            self.n() as u8,
132            self.z() as u8,
133            self.c() as u8,
134            self.v() as u8,
135            self.q() as u8,
136            self.j() as u8,
137            self.e() as u8,
138            self.a() as u8,
139            self.i() as u8,
140            self.f() as u8,
141            self.t() as u8,
142            self.mode(),
143        )
144    }
145}
146
147#[cfg(feature = "defmt")]
148impl defmt::Format for Cpsr {
149    fn format(&self, f: defmt::Formatter) {
150        defmt::write!(f, "CPSR {{ N={0=31..32} Z={0=30..31} C={0=29..30} V={0=28..29} Q={0=27..28} J={0=24..25} E={0=9..10} A={0=8..9} I={0=7..8} F={0=6..7} T={0=5..6} MODE={0=0..5} }}", self.raw_value())
151    }
152}