]>
Commit | Line | Data |
---|---|---|
0731742a XL |
1 | //! ARM compiler specific intrinsics |
2 | //! | |
3 | //! # References | |
4 | //! | |
5 | //! - [ARM Compiler v 6.10 - armclang Reference Guide][arm_comp_ref] | |
6 | //! | |
7 | //! [arm_comp_ref]: https://developer.arm.com/docs/100067/0610 | |
8 | ||
9 | #[cfg(test)] | |
416331ca | 10 | use stdarch_test::assert_instr; |
0731742a XL |
11 | |
12 | /// Inserts a breakpoint instruction. | |
13 | /// | |
14 | /// `val` is a compile-time constant integer in range `[0, 255]`. | |
15 | /// | |
16 | /// The breakpoint instruction inserted is: | |
17 | /// | |
18 | /// * `BKPT` when compiling as T32, | |
19 | /// * `BRK` when compiling as A32 or A64. | |
20 | /// | |
21 | /// # Safety | |
22 | /// | |
23 | /// If `val` is out-of-range the behavior is **undefined**. | |
24 | /// | |
25 | /// # Note | |
26 | /// | |
27 | /// [ARM's documentation][arm_docs] defines that `__breakpoint` accepts the | |
28 | /// following values for `val`: | |
29 | /// | |
30 | /// - `0...65535` when compiling as A32 or A64, | |
31 | /// - `0...255` when compiling as T32. | |
32 | /// | |
33 | /// The current implementation only accepts values in range `[0, 255]` - if the | |
34 | /// value is out-of-range the behavior is **undefined**. | |
35 | /// | |
36 | /// [arm_docs]: https://developer.arm.com/docs/100067/latest/compiler-specific-intrinsics/__breakpoint-intrinsic | |
37 | #[cfg_attr(all(test, target_arch = "arm"), assert_instr(bkpt, val = 0))] | |
38 | #[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(brk, val = 0))] | |
39 | #[inline(always)] | |
40 | #[rustc_args_required_const(0)] | |
41 | pub unsafe fn __breakpoint(val: i32) { | |
42 | // Ensure that this compiles correctly on non-arm architectures, so libstd | |
43 | // doc builds work. The proper macro will shadow this definition below. | |
44 | #[allow(unused_macros)] | |
45 | macro_rules! call { | |
46 | ($e:expr) => { | |
47 | () | |
48 | }; | |
49 | } | |
50 | ||
51 | #[cfg(target_arch = "arm")] | |
52 | macro_rules! call { | |
53 | ($imm8:expr) => { | |
ba9703b0 | 54 | llvm_asm!(concat!("BKPT ", stringify!($imm8)) : : : : "volatile") |
0731742a XL |
55 | } |
56 | } | |
57 | ||
58 | #[cfg(target_arch = "aarch64")] | |
59 | macro_rules! call { | |
60 | ($imm8:expr) => { | |
ba9703b0 | 61 | llvm_asm!(concat!("BRK ", stringify!($imm8)) : : : : "volatile") |
0731742a XL |
62 | } |
63 | } | |
64 | ||
65 | // We can't `panic!` inside this intrinsic, so we can't really validate the | |
66 | // arguments here. If `val` is out-of-range this macro uses `val == 255`: | |
67 | constify_imm8!(val, call); | |
68 | } |