core/stdarch/crates/core_arch/src/arm_shared/hints.rs
1// # References
2//
3// - Section 7.4 "Hints" of ACLE
4// - Section 7.7 "NOP" of ACLE
5
6/// Generates a WFI (wait for interrupt) hint instruction, or nothing.
7///
8/// The WFI instruction allows (but does not require) the processor to enter a
9/// low-power state until one of a number of asynchronous events occurs.
10// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M
11// LLVM says "instruction requires: armv6k"
12#[cfg(any(
13 target_feature = "v6",
14 target_arch = "aarch64",
15 target_arch = "arm64ec",
16 doc
17))]
18#[inline(always)]
19#[unstable(feature = "stdarch_arm_hints", issue = "117218")]
20pub fn __wfi() {
21 // SAFETY: The right HINT_WFI constant is passed to the llvm intrinsic。
22 unsafe {
23 hint(HINT_WFI);
24 }
25}
26
27/// Generates a WFE (wait for event) hint instruction, or nothing.
28///
29/// The WFE instruction allows (but does not require) the processor to enter a
30/// low-power state until some event occurs such as a SEV being issued by
31/// another processor.
32// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M
33// LLVM says "instruction requires: armv6k"
34#[cfg(any(
35 target_feature = "v6",
36 target_arch = "aarch64",
37 target_arch = "arm64ec",
38 doc
39))]
40#[inline(always)]
41#[unstable(feature = "stdarch_arm_hints", issue = "117218")]
42pub fn __wfe() {
43 // SAFETY: The right HINT_WFE constant is passed to the llvm intrinsic。
44 unsafe {
45 hint(HINT_WFE);
46 }
47}
48
49/// Generates a SEV (send a global event) hint instruction.
50///
51/// This causes an event to be signaled to all processors in a multiprocessor
52/// system. It is a NOP on a uniprocessor system.
53// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M, 7-M
54// LLVM says "instruction requires: armv6k"
55#[cfg(any(
56 target_feature = "v6",
57 target_arch = "aarch64",
58 target_arch = "arm64ec",
59 doc
60))]
61#[inline(always)]
62#[unstable(feature = "stdarch_arm_hints", issue = "117218")]
63pub fn __sev() {
64 // SAFETY: The right HINT_SEV constant is passed to the llvm intrinsic。
65 unsafe {
66 hint(HINT_SEV);
67 }
68}
69
70/// Generates a send a local event hint instruction.
71///
72/// This causes an event to be signaled to only the processor executing this
73/// instruction. In a multiprocessor system, it is not required to affect the
74/// other processors.
75// LLVM says "instruction requires: armv8"
76#[cfg(any(
77 target_feature = "v8", // 32-bit ARMv8
78 target_arch = "aarch64", // AArch64
79 target_arch = "arm64ec", // Arm64EC
80 doc,
81))]
82#[inline(always)]
83#[unstable(feature = "stdarch_arm_hints", issue = "117218")]
84pub fn __sevl() {
85 // SAFETY: The right HINT_SEVL constant is passed to the llvm intrinsic。
86 unsafe {
87 hint(HINT_SEVL);
88 }
89}
90
91/// Generates a YIELD hint instruction.
92///
93/// This enables multithreading software to indicate to the hardware that it is
94/// performing a task, for example a spin-lock, that could be swapped out to
95/// improve overall system performance.
96// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M
97// LLVM says "instruction requires: armv6k"
98// On ARMv6 in Thumb mode, T2 is required (see Arm DDI0406C Section A8.8.427)
99#[cfg(any(
100 all(target_feature = "v6k", not(target_feature = "thumb-mode")),
101 target_feature = "v6t2",
102 all(target_feature = "v6", target_feature = "mclass"),
103 target_arch = "aarch64",
104 target_arch = "arm64ec",
105 doc
106))]
107#[inline(always)]
108#[unstable(feature = "stdarch_arm_hints", issue = "117218")]
109pub fn __yield() {
110 // SAFETY: The right HINT_YIELD constant is passed to the llvm intrinsic。
111 unsafe {
112 hint(HINT_YIELD);
113 }
114}
115
116/// Generates an unspecified no-op instruction.
117///
118/// Note that not all architectures provide a distinguished NOP instruction. On
119/// those that do, it is unspecified whether this intrinsic generates it or
120/// another instruction. It is not guaranteed that inserting this instruction
121/// will increase execution time.
122#[inline(always)]
123#[unstable(feature = "stdarch_arm_hints", issue = "117218")]
124pub fn __nop() {
125 // SAFETY: `nop` performs no operation.
126 unsafe {
127 crate::arch::asm!("nop", options(nomem, nostack, preserves_flags));
128 }
129}
130
131unsafe extern "llvm-intrinsic" {
132 #[cfg_attr(
133 any(target_arch = "aarch64", target_arch = "arm64ec"),
134 link_name = "llvm.aarch64.hint"
135 )]
136 #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.hint")]
137 fn hint(_: i32);
138}
139
140// from LLVM 7.0.1's lib/Target/ARM/{ARMInstrThumb,ARMInstrInfo,ARMInstrThumb2}.td
141const HINT_NOP: i32 = 0;
142const HINT_YIELD: i32 = 1;
143const HINT_WFE: i32 = 2;
144const HINT_WFI: i32 = 3;
145const HINT_SEV: i32 = 4;
146const HINT_SEVL: i32 = 5;