Skip to main content

aarch32_cpu/
lib.rs

1//! CPU/peripheral support for Arm AArch32
2#![no_std]
3#![deny(missing_docs)]
4#![deny(unsafe_op_in_unsafe_fn)]
5#![deny(clippy::missing_safety_doc)]
6#![deny(clippy::unnecessary_safety_comment)]
7#![deny(clippy::unnecessary_safety_doc)]
8
9pub mod cache;
10pub mod interrupt;
11pub mod register;
12
13#[cfg(any(
14    doc,
15    arm_architecture = "v7-a",
16    arm_architecture = "v7-r",
17    arm_architecture = "v8-r"
18))]
19#[path = "asmv7.rs"]
20pub mod asm;
21
22#[cfg(not(any(
23    doc,
24    arm_architecture = "v7-a",
25    arm_architecture = "v7-r",
26    arm_architecture = "v8-r"
27)))]
28#[path = "asmv4.rs"]
29pub mod asm;
30
31#[cfg(any(test, doc, arm_architecture = "v7-a", arm_architecture = "v8-r"))]
32pub mod generic_timer;
33
34#[cfg(any(test, arm_profile = "a", arm_profile = "legacy"))]
35pub mod mmu;
36
37#[cfg(any(test, arm_architecture = "v7-r"))]
38pub mod pmsav7;
39
40#[cfg(any(test, arm_architecture = "v8-r"))]
41pub mod pmsav8;
42
43#[cfg(target_arch = "arm")]
44pub mod stacks;
45
46mod critical_section;
47
48/// Generate an SVC call with no parameters.
49///
50/// Puts the first argument in the instruction. Gives you back
51/// the value left in `r0` by the handler.
52///
53/// ```rust,ignore
54/// let value = svc!(0xFF);
55/// ```
56#[macro_export]
57macro_rules! svc {
58    ($num:expr) => { {
59        let retval: u32;
60        unsafe {
61            core::arch::asm!("svc {arg}", arg = const $num, lateout("r0") retval);
62        }
63        retval
64    } }
65}
66
67/// Generate an SVC call with 1 parameters
68///
69/// Puts the first argument in the instruction, and the parameter in r0. Gives you back
70/// the value left in `r0` by the handler.
71///
72/// ```rust,ignore
73/// const SYSCALL_FOO: u32 = 0x100;
74/// let result = svc1!(0x00, SYSCALL_FOO);
75/// ```
76#[macro_export]
77macro_rules! svc1 {
78    ($num:expr, $arg0:expr) => { {
79        let retval: u32;
80        let arg0: u32 = $arg0;
81        unsafe {
82            core::arch::asm!(
83                // Do the SVCall
84                "svc     {arg}",
85                arg = const $num,
86                inout("r0") arg0 => retval);
87        }
88        retval
89    } }
90}
91
92/// Generate an SVC call with 2 parameters
93///
94/// Puts the first argument in the instruction, and the parameters in r0-r1. Gives you back
95/// the value left in `r0` by the handler.
96///
97/// ```rust,ignore
98/// const SYSCALL_FOO: u32 = 0x100;
99/// let result = svc2!(0x00, SYSCALL_FOO, 1);
100/// ```
101#[macro_export]
102macro_rules! svc2 {
103    ($num:expr, $arg0:expr, $arg1:expr) => { {
104        let retval: u32;
105        let arg0: u32 = $arg0;
106        let arg1: u32 = $arg1;
107        unsafe {
108            core::arch::asm!(
109                // Do the SVCall
110                "svc     {arg}",
111                arg = const $num,
112                inout("r0") arg0 => retval,
113                in("r1") arg1);
114        }
115        retval
116    } }
117}
118
119/// Generate an SVC call with 3 parameters
120///
121/// Puts the first argument in the instruction, and the parameters in r0-r2. Gives you back
122/// the value left in `r0` by the handler.
123///
124/// ```rust,ignore
125/// const SYSCALL_FOO: u32 = 0x100;
126/// let result = svc3!(0x00, SYSCALL_FOO, 1, 2);
127/// ```
128#[macro_export]
129macro_rules! svc3 {
130    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr) => { {
131        let retval: u32;
132        let arg0: u32 = $arg0;
133        let arg1: u32 = $arg1;
134        let arg2: u32 = $arg2;
135        unsafe {
136            core::arch::asm!(
137                // Do the SVCall
138                "svc     {arg}",
139                arg = const $num,
140                inout("r0") arg0 => retval,
141                in("r1") arg1,
142                in("r2") arg2);
143        }
144        retval
145    } }
146}
147
148/// Generate an SVC call with 4 parameters
149///
150/// Puts the first argument in the instruction, and the parameters in r0-r3. Gives you back
151/// the value left in `r0` by the handler.
152///
153/// ```rust,ignore
154/// const SYSCALL_FOO: u32 = 0x100;
155/// let result = svc4!(0x00, SYSCALL_FOO, 1, 2, 3);
156/// ```
157#[macro_export]
158macro_rules! svc4 {
159    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr) => { {
160        let retval: u32;
161        let arg0: u32 = $arg0;
162        let arg1: u32 = $arg1;
163        let arg2: u32 = $arg2;
164        let arg3: u32 = $arg3;
165        unsafe {
166            core::arch::asm!(
167                // Do the SVCall
168                "svc     {arg}",
169                arg = const $num,
170                inout("r0") arg0 => retval,
171                in("r1") arg1,
172                in("r2") arg2,
173                in("r3") arg3);
174        }
175        retval
176    } }
177}
178
179/// Generate an SVC call with 5 parameters
180///
181/// Puts the first argument in the instruction, and the parameters in r0-r4. Gives you back
182/// the value left in `r0` by the handler.
183///
184/// ```rust,ignore
185/// const SYSCALL_FOO: u32 = 0x100;
186/// let result = svc5!(0x00, SYSCALL_FOO, 1, 2, 3, 4);
187/// ```
188#[macro_export]
189macro_rules! svc5 {
190    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr) => { {
191        let retval: u32;
192        let arg0: u32 = $arg0;
193        let arg1: u32 = $arg1;
194        let arg2: u32 = $arg2;
195        let arg3: u32 = $arg3;
196        let arg4: u32 = $arg4;
197        unsafe {
198            core::arch::asm!(
199                // Do the SVCall
200                "svc     {arg}",
201                arg = const $num,
202                inout("r0") arg0 => retval,
203                in("r1") arg1,
204                in("r2") arg2,
205                in("r3") arg3,
206                in("r4") arg4);
207        }
208        retval
209    } }
210}
211
212/// Generate an SVC call with 6 parameters
213///
214/// Puts the first argument in the instruction, and the parameters in r0-r5. Gives you back
215/// the value left in `r0` by the handler.
216///
217/// ```rust,ignore
218/// const SYSCALL_FOO: u32 = 0x100;
219/// let result = svc6!(0x00, SYSCALL_FOO, 1, 2, 3, 4, 5);
220/// ```
221#[macro_export]
222macro_rules! svc6 {
223    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr) => { {
224        let retval: u32;
225        let arg0: u32 = $arg0;
226        let arg1: u32 = $arg1;
227        let arg2: u32 = $arg2;
228        let arg3: u32 = $arg3;
229        let arg4: u32 = $arg4;
230        let arg5: u32 = $arg5;
231        unsafe {
232            core::arch::asm!(
233                // Do the SVCall
234                "svc     {arg}",
235                arg = const $num,
236                inout("r0") arg0 => retval,
237                in("r1") arg1,
238                in("r2") arg2,
239                in("r3") arg3,
240                in("r4") arg4,
241                in("r5") arg5);
242        }
243        retval
244    } }
245}
246
247/// Generate an HVC call with the given argument.
248#[macro_export]
249macro_rules! hvc {
250    ($r0:expr) => {
251        unsafe {
252            core::arch::asm!("hvc {arg}", arg = const $r0);
253        }
254    }
255}
256
257/// Generate an HVC call with 1 parameters
258///
259/// Puts the first argument in the instruction, and the parameter in r0. Gives you back
260/// the value left in `r0` by the handler.
261///
262/// ```rust,ignore
263/// const HYPERCALL_FOO: u32 = 0x100;
264/// let result = hvc1!(0x00, HYPERCALL_FOO);
265/// ```
266#[macro_export]
267macro_rules! hvc1 {
268    ($num:expr, $arg0:expr) => { {
269        let retval: u32;
270        let arg0: u32 = $arg0;
271        unsafe {
272            core::arch::asm!(
273                // Do the Hyper-call
274                "hvc     {arg}",
275                arg = const $num,
276                inout("r0") arg0 => retval);
277        }
278        retval
279    } }
280}
281
282/// Generate an HVC call with 2 parameters
283///
284/// Puts the first argument in the instruction, and the parameters in r0-r1. Gives you back
285/// the value left in `r0` by the handler.
286///
287/// ```rust,ignore
288/// const HYPERCALL_FOO: u32 = 0x100;
289/// let result = hvc2!(0x00, HYPERCALL_FOO, 1);
290/// ```
291#[macro_export]
292macro_rules! hvc2 {
293    ($num:expr, $arg0:expr, $arg1:expr) => { {
294        let retval: u32;
295        let arg0: u32 = $arg0;
296        let arg1: u32 = $arg1;
297        unsafe {
298            core::arch::asm!(
299                // Do the Hyper-call
300                "hvc     {arg}",
301                arg = const $num,
302                inout("r0") arg0 => retval,
303                in("r1") arg1);
304        }
305        retval
306    } }
307}
308
309/// Generate an HVC call with 3 parameters
310///
311/// Puts the first argument in the instruction, and the parameters in r0-r2. Gives you back
312/// the value left in `r0` by the handler.
313///
314/// ```rust,ignore
315/// const HYPERCALL_FOO: u32 = 0x100;
316/// let result = hvc3!(0x00, HYPERCALL_FOO, 1, 2);
317/// ```
318#[macro_export]
319macro_rules! hvc3 {
320    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr) => { {
321        let retval: u32;
322        let arg0: u32 = $arg0;
323        let arg1: u32 = $arg1;
324        let arg2: u32 = $arg2;
325        unsafe {
326            core::arch::asm!(
327                // Do the Hyper-call
328                "hvc     {arg}",
329                arg = const $num,
330                inout("r0") arg0 => retval,
331                in("r1") arg1,
332                in("r2") arg2);
333        }
334        retval
335    } }
336}
337
338/// Generate an HVC call with 4 parameters
339///
340/// Puts the first argument in the instruction, and the parameters in r0-r3. Gives you back
341/// the value left in `r0` by the handler.
342///
343/// ```rust,ignore
344/// const HYPERCALL_FOO: u32 = 0x100;
345/// let result = hvc4!(0x00, HYPERCALL_FOO, 1, 2, 3);
346/// ```
347#[macro_export]
348macro_rules! hvc4 {
349    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr) => { {
350        let retval: u32;
351        let arg0: u32 = $arg0;
352        let arg1: u32 = $arg1;
353        let arg2: u32 = $arg2;
354        let arg3: u32 = $arg3;
355        unsafe {
356            core::arch::asm!(
357                // Do the Hyper-call
358                "hvc     {arg}",
359                arg = const $num,
360                inout("r0") arg0 => retval,
361                in("r1") arg1,
362                in("r2") arg2,
363                in("r3") arg3);
364        }
365        retval
366    } }
367}
368
369/// Generate an HVC call with 5 parameters
370///
371/// Puts the first argument in the instruction, and the parameters in r0-r4. Gives you back
372/// the value left in `r0` by the handler.
373///
374/// ```rust,ignore
375/// const HYPERCALL_FOO: u32 = 0x100;
376/// let result = hvc5!(0x00, HYPERCALL_FOO, 1, 2, 3, 4);
377/// ```
378#[macro_export]
379macro_rules! hvc5 {
380    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr) => { {
381        let retval: u32;
382        let arg0: u32 = $arg0;
383        let arg1: u32 = $arg1;
384        let arg2: u32 = $arg2;
385        let arg3: u32 = $arg3;
386        let arg4: u32 = $arg4;
387        unsafe {
388            core::arch::asm!(
389                // Do the Hyper-call
390                "hvc     {arg}",
391                arg = const $num,
392                inout("r0") arg0 => retval,
393                in("r1") arg1,
394                in("r2") arg2,
395                in("r3") arg3,
396                in("r4") arg4);
397        }
398        retval
399    } }
400}
401
402/// Generate an HVC call with 6 parameters
403///
404/// Puts the first argument in the instruction, and the parameters in r0-r5. Gives you back
405/// the value left in `r0` by the handler.
406///
407/// ```rust,ignore
408/// const HYPERCALL_FOO: u32 = 0x100;
409/// let result = hvc6!(0x00, HYPERCALL_FOO, 1, 2, 3, 4, 5);
410/// ```
411#[macro_export]
412macro_rules! hvc6 {
413    ($num:expr, $arg0:expr, $arg1:expr, $arg2:expr, $arg3:expr, $arg4:expr, $arg5:expr) => { {
414        let retval: u32;
415        let arg0: u32 = $arg0;
416        let arg1: u32 = $arg1;
417        let arg2: u32 = $arg2;
418        let arg3: u32 = $arg3;
419        let arg4: u32 = $arg4;
420        let arg5: u32 = $arg5;
421        unsafe {
422            core::arch::asm!(
423                // Do the Hyper-call
424                "hvc     {arg}",
425                arg = const $num,
426                inout("r0") arg0 => retval,
427                in("r1") arg1,
428                in("r2") arg2,
429                in("r3") arg3,
430                in("r4") arg4,
431                in("r5") arg5);
432        }
433        retval
434    } }
435}