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