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}