Skip to content

Commit c6be39c

Browse files
japaricgnzlbg
authored andcommitted
remove cmsis module; add acle module
ACLE (ARM C Language Extensions) is more general (supports ARMv4 to ARMv8) than CMSIS (ARMv7-M and ARMv7-R)
1 parent 4e9f91e commit c6be39c

File tree

16 files changed

+691
-335
lines changed

16 files changed

+691
-335
lines changed

crates/core_arch/src/aarch64/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ pub use self::crypto::*;
1818
mod crc;
1919
pub use self::crc::*;
2020

21+
pub use super::acle::*;
22+
2123
#[cfg(test)]
2224
use stdsimd_test::assert_instr;
2325

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//! Access types available on all architectures
2+
3+
/// Full system is the required shareability domain, reads and writes are the
4+
/// required access types
5+
pub struct SY;
6+
7+
dmb_dsb!(SY);
8+
9+
impl super::super::sealed::Isb for SY {
10+
#[inline(always)]
11+
unsafe fn __isb(&self) {
12+
asm!("ISB SY" : : : "memory" : "volatile")
13+
}
14+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Reference: Section 7.4 "Hints" of ACLE
2+
3+
macro_rules! dmb_dsb {
4+
($A:ident) => {
5+
impl super::super::sealed::Dmb for $A {
6+
#[inline(always)]
7+
unsafe fn __dmb(&self) {
8+
asm!(concat!("DMB ", stringify!($A)) : : : "memory" : "volatile")
9+
}
10+
}
11+
12+
impl super::super::sealed::Dsb for $A {
13+
#[inline(always)]
14+
unsafe fn __dsb(&self) {
15+
asm!(concat!("DSB ", stringify!($A)) : : : "memory" : "volatile")
16+
}
17+
}
18+
};
19+
}
20+
21+
mod common;
22+
23+
pub use self::common::*;
24+
25+
#[cfg(not(target_feature = "mclass"))]
26+
mod not_mclass;
27+
28+
#[cfg(not(target_feature = "mclass"))]
29+
pub use self::not_mclass::*;
30+
31+
#[cfg(target_arch = "aarch64")]
32+
mod v8;
33+
34+
#[cfg(target_arch = "aarch64")]
35+
pub use self::v8::*;
36+
37+
/// Generates a DMB (data memory barrier) instruction or equivalent CP15 instruction.
38+
///
39+
/// DMB ensures the observed ordering of memory accesses. Memory accesses of the specified type
40+
/// issued before the DMB are guaranteed to be observed (in the specified scope) before memory
41+
/// accesses issued after the DMB.
42+
///
43+
/// For example, DMB should be used between storing data, and updating a flag variable that makes
44+
/// that data available to another core.
45+
///
46+
/// The __dmb() intrinsic also acts as a compiler memory barrier of the appropriate type.
47+
#[inline(always)]
48+
pub unsafe fn __dmb<A>(arg: A)
49+
where
50+
A: super::sealed::Dmb,
51+
{
52+
arg.__dmb()
53+
}
54+
55+
/// Generates a DSB (data synchronization barrier) instruction or equivalent CP15 instruction.
56+
///
57+
/// DSB ensures the completion of memory accesses. A DSB behaves as the equivalent DMB and has
58+
/// additional properties. After a DSB instruction completes, all memory accesses of the specified
59+
/// type issued before the DSB are guaranteed to have completed.
60+
///
61+
/// The __dsb() intrinsic also acts as a compiler memory barrier of the appropriate type.
62+
#[inline(always)]
63+
pub unsafe fn __dsb<A>(arg: A)
64+
where
65+
A: super::sealed::Dsb,
66+
{
67+
arg.__dsb()
68+
}
69+
70+
/// Generates an ISB (instruction synchronization barrier) instruction or equivalent CP15
71+
/// instruction.
72+
///
73+
/// This instruction flushes the processor pipeline fetch buffers, so that following instructions
74+
/// are fetched from cache or memory.
75+
///
76+
/// An ISB is needed after some system maintenance operations. An ISB is also needed before
77+
/// transferring control to code that has been loaded or modified in memory, for example by an
78+
/// overlay mechanism or just-in-time code generator. (Note that if instruction and data caches are
79+
/// separate, privileged cache maintenance operations would be needed in order to unify the caches.)
80+
///
81+
/// The only supported argument for the __isb() intrinsic is 15, corresponding to the SY (full
82+
/// system) scope of the ISB instruction.
83+
#[inline(always)]
84+
pub unsafe fn __isb<A>(arg: A)
85+
where
86+
A: super::sealed::Isb,
87+
{
88+
arg.__isb()
89+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//! Access types available on v7 and v8 but not on v7(E)-M or v8-M
2+
3+
/// Full system is the required shareability domain, writes are the required
4+
/// access type
5+
pub struct ST;
6+
7+
dmb_dsb!(ST);
8+
9+
/// Inner Shareable is the required shareability domain, reads and writes are
10+
/// the required access types
11+
pub struct ISH;
12+
13+
dmb_dsb!(ISH);
14+
15+
/// Inner Shareable is the required shareability domain, writes are the required
16+
/// access type
17+
pub struct ISHST;
18+
19+
dmb_dsb!(ISHST);
20+
21+
/// Non-shareable is the required shareability domain, reads and writes are the
22+
/// required access types
23+
pub struct NSH;
24+
25+
dmb_dsb!(NSH);
26+
27+
/// Non-shareable is the required shareability domain, writes are the required
28+
/// access type
29+
pub struct NSHST;
30+
31+
dmb_dsb!(NSHST);
32+
33+
/// Outer Shareable is the required shareability domain, reads and writes are
34+
/// the required access types
35+
pub struct OSH;
36+
37+
dmb_dsb!(OSH);
38+
39+
/// Outer Shareable is the required shareability domain, writes are the required
40+
/// access type
41+
pub struct OSHST;
42+
43+
dmb_dsb!(OSHST);
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/// Full system is the required shareability domain, reads are the required
2+
/// access type
3+
pub struct LD;
4+
5+
dmb_dsb!(LD);
6+
7+
/// Inner Shareable is the required shareability domain, reads are the required
8+
/// access type
9+
pub struct ISHLD;
10+
11+
dmb_dsb!(ISHLD);
12+
13+
/// Non-shareable is the required shareability domain, reads are the required
14+
/// access type
15+
pub struct NSHLD;
16+
17+
dmb_dsb!(NSHLD);
18+
19+
/// Outher Shareable is the required shareability domain, reads are the required
20+
/// access type
21+
pub struct OSHLD;
22+
23+
dmb_dsb!(OSHLD);

crates/core_arch/src/acle/dsp.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//! # References:
2+
//!
3+
//! - Section 8.3 "16-bit multiplications"
4+
//! - Section 8.4 "Saturating intrinsics"
5+
//!
6+
//! Intrinsics that could live here:
7+
//!
8+
//! - __smulbb
9+
//! - __smulbt
10+
//! - __smultb
11+
//! - __smultt
12+
//! - __smulwb
13+
//! - __smulwt
14+
//! - __ssat
15+
//! - __usat
16+
//! - __qadd
17+
//! - __qsub
18+
//! - __qdbl
19+
//! - __smlabb
20+
//! - __smlabt
21+
//! - __smlatb
22+
//! - __smlatt
23+
//! - __smlawb
24+
//! - __smlawt

crates/core_arch/src/acle/hints.rs

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
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(target_feature = "v6k", target_arch = "aarch64"))]
13+
#[inline(always)]
14+
pub unsafe fn __wfi() {
15+
asm!("WFI" : : : : "volatile")
16+
}
17+
18+
/// Generates a WFE (wait for event) hint instruction, or nothing.
19+
///
20+
/// The WFE instruction allows (but does not require) the processor to enter a
21+
/// low-power state until some event occurs such as a SEV being issued by
22+
/// another processor.
23+
// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M
24+
// LLVM says "instruction requires: armv6k"
25+
#[cfg(any(target_feature = "v6k", target_arch = "aarch64"))]
26+
#[inline(always)]
27+
pub unsafe fn __wfe() {
28+
asm!("WFE" : : : : "volatile")
29+
}
30+
31+
/// Generates a SEV (send a global event) hint instruction.
32+
///
33+
/// This causes an event to be signaled to all processors in a multiprocessor
34+
/// system. It is a NOP on a uniprocessor system.
35+
// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M, 7-M
36+
// LLVM says "instruction requires: armv6k"
37+
#[cfg(any(target_feature = "v6k", target_arch = "aarch64"))]
38+
#[inline(always)]
39+
pub unsafe fn __sev() {
40+
asm!("SEV" : : : : "volatile")
41+
}
42+
43+
/// Generates a send a local event hint instruction.
44+
///
45+
/// This causes an event to be signaled to only the processor executing this
46+
/// instruction. In a multiprocessor system, it is not required to affect the
47+
/// other processors.
48+
// LLVM says "instruction requires: armv8"
49+
#[cfg(target_arch = "aarch64")]
50+
#[inline(always)]
51+
pub unsafe fn __sevl() {
52+
asm!("SEVL" : : : : "volatile")
53+
}
54+
55+
/// Generates a YIELD hint instruction.
56+
///
57+
/// This enables multithreading software to indicate to the hardware that it is
58+
/// performing a task, for example a spin-lock, that could be swapped out to
59+
/// improve overall system performance.
60+
// Section 10.1 of ACLE says that the supported arches are: 8, 6K, 6-M
61+
// LLVM says "instruction requires: armv6k"
62+
#[cfg(any(target_feature = "v6k", target_arch = "aarch64"))]
63+
#[inline(always)]
64+
pub unsafe fn __yield() {
65+
asm!("YIELD" : : : : "volatile")
66+
}
67+
68+
/// Generates a DBG instruction.
69+
///
70+
/// This provides a hint to debugging and related systems. The argument must be
71+
/// a constant integer from 0 to 15 inclusive. See implementation documentation
72+
/// for the effect (if any) of this instruction and the meaning of the
73+
/// argument. This is available only when compliling for AArch32.
74+
// Section 10.1 of ACLE says that the supported arches are: 7, 7-M
75+
// LLVM says "instruction requires: thumb2" OR "instruction requires: armv7"
76+
#[cfg(target_feature = "v6t2")]
77+
#[inline(always)]
78+
#[rustc_args_required_const(0)]
79+
pub unsafe fn __dbg(imm4: u32) {
80+
macro_rules! call {
81+
($imm4:expr) => {
82+
asm!(concat!("DBG ", stringify!($imm4)) : : : : "volatile")
83+
}
84+
}
85+
86+
match imm4 & 0b1111 {
87+
0 => call!(0),
88+
1 => call!(1),
89+
2 => call!(2),
90+
3 => call!(3),
91+
4 => call!(4),
92+
5 => call!(5),
93+
6 => call!(6),
94+
7 => call!(7),
95+
8 => call!(8),
96+
9 => call!(9),
97+
10 => call!(10),
98+
11 => call!(11),
99+
12 => call!(12),
100+
13 => call!(13),
101+
14 => call!(14),
102+
_ => call!(15),
103+
}
104+
}
105+
106+
/// Generates an unspecified no-op instruction.
107+
///
108+
/// Note that not all architectures provide a distinguished NOP instruction. On
109+
/// those that do, it is unspecified whether this intrinsic generates it or
110+
/// another instruction. It is not guaranteed that inserting this instruction
111+
/// will increase execution time.
112+
#[inline(always)]
113+
pub unsafe fn __nop() {
114+
asm!("NOP" : : : : "volatile")
115+
}

0 commit comments

Comments
 (0)