Remove obscure & rarely used ARM intrinsics
In almost all cases it is preferable to use the stable `asm!` instead of calling these intrinsics. This PR removes the following unstable intrinsics: - `__breakpoint` Clang extension, not part of ACLE. - `brk`: undocumented - `_rev*`, `_clz*`, `_rbit*`: use methods on integer types instead - `__ldrex`, `__strex`: deprecated in ACLE, hard to use correctly - Register access API: API doesn't match ACLE, better to just use asm Also considered for deletion, but not included in this PR: - Barriers: `__isb`, `__dsb`, `__dmb` - Hints: `__wfi`, `__wfe`, `__sev`, `__sevl`, `__yield`, `__nop`
This commit is contained in:
@@ -1,23 +0,0 @@
|
|||||||
//! ARM compiler specific intrinsics
|
|
||||||
//!
|
|
||||||
//! # References
|
|
||||||
//!
|
|
||||||
//! - [ARM Compiler v 6.10 - armclang Reference Guide][arm_comp_ref]
|
|
||||||
//!
|
|
||||||
//! [arm_comp_ref]: https://developer.arm.com/docs/100067/0610
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
use stdarch_test::assert_instr;
|
|
||||||
|
|
||||||
/// Inserts a breakpoint instruction.
|
|
||||||
///
|
|
||||||
/// `VAL` is a compile-time constant integer in range `[0, 65535]`.
|
|
||||||
///
|
|
||||||
/// The breakpoint instruction inserted is `BRK` on A64.
|
|
||||||
#[cfg_attr(test, assert_instr(brk, VAL = 0))]
|
|
||||||
#[inline(always)]
|
|
||||||
#[rustc_legacy_const_generics(0)]
|
|
||||||
pub unsafe fn __breakpoint<const VAL: i32>() {
|
|
||||||
static_assert_uimm_bits!(VAL, 16);
|
|
||||||
crate::arch::asm!("brk {}", const VAL);
|
|
||||||
}
|
|
||||||
@@ -6,9 +6,6 @@
|
|||||||
//! [arm_ref]: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0073a/IHI0073A_arm_neon_intrinsics_ref.pdf
|
//! [arm_ref]: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0073a/IHI0073A_arm_neon_intrinsics_ref.pdf
|
||||||
//! [arm_dat]: https://developer.arm.com/technologies/neon/intrinsics
|
//! [arm_dat]: https://developer.arm.com/technologies/neon/intrinsics
|
||||||
|
|
||||||
mod v8;
|
|
||||||
pub use self::v8::*;
|
|
||||||
|
|
||||||
mod neon;
|
mod neon;
|
||||||
pub use self::neon::*;
|
pub use self::neon::*;
|
||||||
|
|
||||||
@@ -23,19 +20,8 @@ pub use self::prefetch::*;
|
|||||||
|
|
||||||
pub use super::arm_shared::*;
|
pub use super::arm_shared::*;
|
||||||
|
|
||||||
mod armclang;
|
|
||||||
|
|
||||||
pub use self::armclang::*;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use stdarch_test::assert_instr;
|
use stdarch_test::assert_instr;
|
||||||
|
|
||||||
/// Generates the trap instruction `BRK 1`
|
|
||||||
#[cfg_attr(test, assert_instr(brk))]
|
|
||||||
#[inline]
|
|
||||||
pub unsafe fn brk() -> ! {
|
|
||||||
crate::intrinsics::abort()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) mod test_support;
|
pub(crate) mod test_support;
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
//! ARMv8 intrinsics.
|
|
||||||
//!
|
|
||||||
//! The reference is [ARMv8-A Reference Manual][armv8].
|
|
||||||
//!
|
|
||||||
//! [armv8]: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.
|
|
||||||
//! ddi0487a.k_10775/index.html
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
use stdarch_test::assert_instr;
|
|
||||||
|
|
||||||
/// Reverse the order of the bytes.
|
|
||||||
#[inline]
|
|
||||||
#[cfg_attr(test, assert_instr(rev))]
|
|
||||||
pub unsafe fn _rev_u64(x: u64) -> u64 {
|
|
||||||
x.swap_bytes() as u64
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Count Leading Zeros.
|
|
||||||
#[inline]
|
|
||||||
#[cfg_attr(test, assert_instr(clz))]
|
|
||||||
pub unsafe fn _clz_u64(x: u64) -> u64 {
|
|
||||||
x.leading_zeros() as u64
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reverse the bit order.
|
|
||||||
#[inline]
|
|
||||||
#[cfg_attr(test, assert_instr(rbit))]
|
|
||||||
pub unsafe fn _rbit_u64(x: u64) -> u64 {
|
|
||||||
crate::intrinsics::bitreverse(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Counts the leading most significant bits set.
|
|
||||||
///
|
|
||||||
/// When all bits of the operand are set it returns the size of the operand in
|
|
||||||
/// bits.
|
|
||||||
#[inline]
|
|
||||||
#[cfg_attr(test, assert_instr(cls))]
|
|
||||||
pub unsafe fn _cls_u32(x: u32) -> u32 {
|
|
||||||
u32::leading_zeros((((((x as i32) >> 31) as u32) ^ x) << 1) | 1) as u32
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Counts the leading most significant bits set.
|
|
||||||
///
|
|
||||||
/// When all bits of the operand are set it returns the size of the operand in
|
|
||||||
/// bits.
|
|
||||||
#[inline]
|
|
||||||
#[cfg_attr(test, assert_instr(cls))]
|
|
||||||
pub unsafe fn _cls_u64(x: u64) -> u64 {
|
|
||||||
u64::leading_zeros((((((x as i64) >> 63) as u64) ^ x) << 1) | 1) as u64
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::core_arch::aarch64::v8;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn _rev_u64() {
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(
|
|
||||||
v8::_rev_u64(0b0000_0000_1111_1111_0000_0000_1111_1111_u64),
|
|
||||||
0b1111_1111_0000_0000_1111_1111_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_u64
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn _clz_u64() {
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(v8::_clz_u64(0b0000_1010u64), 60u64);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn _rbit_u64() {
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(
|
|
||||||
v8::_rbit_u64(0b0000_0000_1111_1101_0000_0000_1111_1111_u64),
|
|
||||||
0b1111_1111_0000_0000_1011_1111_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_u64
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn _cls_u32() {
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(
|
|
||||||
v8::_cls_u32(0b1111_1111_1111_1111_0000_0000_1111_1111_u32),
|
|
||||||
15_u32
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn _cls_u64() {
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(
|
|
||||||
v8::_cls_u64(
|
|
||||||
0b1111_1111_1111_1111_0000_0000_1111_1111_0000_0000_0000_0000_0000_0000_0000_0000_u64
|
|
||||||
),
|
|
||||||
15_u64
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
//! ARM compiler specific intrinsics
|
|
||||||
//!
|
|
||||||
//! # References
|
|
||||||
//!
|
|
||||||
//! - [ARM Compiler v 6.10 - armclang Reference Guide][arm_comp_ref]
|
|
||||||
//!
|
|
||||||
//! [arm_comp_ref]: https://developer.arm.com/docs/100067/0610
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
use stdarch_test::assert_instr;
|
|
||||||
|
|
||||||
/// Inserts a breakpoint instruction.
|
|
||||||
///
|
|
||||||
/// `VAL` is a compile-time constant integer in range `[0, 255]`.
|
|
||||||
///
|
|
||||||
/// The breakpoint instruction inserted is `BKPT` on A32/T32.
|
|
||||||
///
|
|
||||||
/// # Note
|
|
||||||
///
|
|
||||||
/// [ARM's documentation][arm_docs] defines that `__breakpoint` accepts the
|
|
||||||
/// following values for `VAL`:
|
|
||||||
///
|
|
||||||
/// - `0...65535` when compiling as A32,
|
|
||||||
/// - `0...255` when compiling as T32.
|
|
||||||
///
|
|
||||||
/// The current implementation only accepts values in range `[0, 255]`.
|
|
||||||
///
|
|
||||||
/// [arm_docs]: https://developer.arm.com/docs/100067/latest/compiler-specific-intrinsics/__breakpoint-intrinsic
|
|
||||||
#[cfg_attr(test, assert_instr(bkpt, VAL = 0))]
|
|
||||||
#[inline(always)]
|
|
||||||
#[rustc_legacy_const_generics(0)]
|
|
||||||
pub unsafe fn __breakpoint<const VAL: i32>() {
|
|
||||||
static_assert_uimm_bits!(VAL, 8);
|
|
||||||
crate::arch::asm!("bkpt #{}", const VAL);
|
|
||||||
}
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
// Reference: Section 5.4.4 "LDREX / STREX" of ACLE
|
|
||||||
|
|
||||||
/// Removes the exclusive lock created by LDREX
|
|
||||||
// Supported: v6, v6K, v7-M, v7-A, v7-R
|
|
||||||
// Not supported: v5, v6-M
|
|
||||||
// NOTE: there's no dedicated CLREX instruction in v6 (<v6k); to clear the exclusive monitor users
|
|
||||||
// have to do a dummy STREX operation
|
|
||||||
#[cfg(any(
|
|
||||||
all(target_feature = "v6k", not(target_feature = "mclass")), // excludes v6-M
|
|
||||||
all(target_feature = "v7", target_feature = "mclass"), // v7-M
|
|
||||||
doc
|
|
||||||
))]
|
|
||||||
pub unsafe fn __clrex() {
|
|
||||||
extern "unadjusted" {
|
|
||||||
#[link_name = "llvm.arm.clrex"]
|
|
||||||
fn clrex();
|
|
||||||
}
|
|
||||||
|
|
||||||
clrex()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Executes an exclusive LDR instruction for 8 bit value.
|
|
||||||
// Supported: v6K, v7-M, v7-A, v7-R
|
|
||||||
// Not supported: v5, v6, v6-M
|
|
||||||
#[cfg(any(
|
|
||||||
target_feature = "v6k", // includes v7-M but excludes v6-M
|
|
||||||
doc
|
|
||||||
))]
|
|
||||||
pub unsafe fn __ldrexb(p: *const u8) -> u8 {
|
|
||||||
extern "unadjusted" {
|
|
||||||
#[link_name = "llvm.arm.ldrex.p0i8"]
|
|
||||||
fn ldrex8(p: *const u8) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
ldrex8(p) as u8
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Executes an exclusive LDR instruction for 16 bit value.
|
|
||||||
// Supported: v6K, v7-M, v7-A, v7-R, v8
|
|
||||||
// Not supported: v5, v6, v6-M
|
|
||||||
#[cfg(any(
|
|
||||||
target_feature = "v6k", // includes v7-M but excludes v6-M
|
|
||||||
doc
|
|
||||||
))]
|
|
||||||
pub unsafe fn __ldrexh(p: *const u16) -> u16 {
|
|
||||||
extern "unadjusted" {
|
|
||||||
#[link_name = "llvm.arm.ldrex.p0i16"]
|
|
||||||
fn ldrex16(p: *const u16) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
ldrex16(p) as u16
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Executes an exclusive LDR instruction for 32 bit value.
|
|
||||||
// Supported: v6, v7-M, v6K, v7-A, v7-R, v8
|
|
||||||
// Not supported: v5, v6-M
|
|
||||||
#[cfg(any(
|
|
||||||
all(target_feature = "v6", not(target_feature = "mclass")), // excludes v6-M
|
|
||||||
all(target_feature = "v7", target_feature = "mclass"), // v7-M
|
|
||||||
doc
|
|
||||||
))]
|
|
||||||
pub unsafe fn __ldrex(p: *const u32) -> u32 {
|
|
||||||
extern "unadjusted" {
|
|
||||||
#[link_name = "llvm.arm.ldrex.p0i32"]
|
|
||||||
fn ldrex32(p: *const u32) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
ldrex32(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Executes an exclusive STR instruction for 8 bit values
|
|
||||||
///
|
|
||||||
/// Returns `0` if the operation succeeded, or `1` if it failed
|
|
||||||
// supported: v6K, v7-M, v7-A, v7-R
|
|
||||||
// Not supported: v5, v6, v6-M
|
|
||||||
#[cfg(any(
|
|
||||||
target_feature = "v6k", // includes v7-M but excludes v6-M
|
|
||||||
doc
|
|
||||||
))]
|
|
||||||
pub unsafe fn __strexb(value: u32, addr: *mut u8) -> u32 {
|
|
||||||
extern "unadjusted" {
|
|
||||||
#[link_name = "llvm.arm.strex.p0i8"]
|
|
||||||
fn strex8(value: u32, addr: *mut u8) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
strex8(value, addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Executes an exclusive STR instruction for 16 bit values
|
|
||||||
///
|
|
||||||
/// Returns `0` if the operation succeeded, or `1` if it failed
|
|
||||||
// Supported: v6K, v7-M, v7-A, v7-R, v8
|
|
||||||
// Not supported: v5, v6, v6-M
|
|
||||||
#[cfg(target_feature = "aarch64")]
|
|
||||||
#[cfg(any(
|
|
||||||
target_feature = "v6k", // includes v7-M but excludes v6-M
|
|
||||||
doc
|
|
||||||
))]
|
|
||||||
pub unsafe fn __strexh(value: u16, addr: *mut u16) -> u32 {
|
|
||||||
extern "unadjusted" {
|
|
||||||
#[link_name = "llvm.arm.strex.p0i16"]
|
|
||||||
fn strex16(value: u32, addr: *mut u16) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
strex16(value as u32, addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Executes an exclusive STR instruction for 32 bit values
|
|
||||||
///
|
|
||||||
/// Returns `0` if the operation succeeded, or `1` if it failed
|
|
||||||
// Supported: v6, v7-M, v6K, v7-A, v7-R, v8
|
|
||||||
// Not supported: v5, v6-M
|
|
||||||
#[cfg(any(
|
|
||||||
all(target_feature = "v6", not(target_feature = "mclass")), // excludes v6-M
|
|
||||||
all(target_feature = "v7", target_feature = "mclass"), // v7-M
|
|
||||||
doc
|
|
||||||
))]
|
|
||||||
pub unsafe fn __strex(value: u32, addr: *mut u32) -> u32 {
|
|
||||||
extern "unadjusted" {
|
|
||||||
#[link_name = "llvm.arm.strex.p0i32"]
|
|
||||||
fn strex32(value: u32, addr: *mut u32) -> u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
strex32(value, addr)
|
|
||||||
}
|
|
||||||
@@ -6,12 +6,6 @@
|
|||||||
//! [arm_ref]: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0073a/IHI0073A_arm_neon_intrinsics_ref.pdf
|
//! [arm_ref]: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0073a/IHI0073A_arm_neon_intrinsics_ref.pdf
|
||||||
//! [arm_dat]: https://developer.arm.com/technologies/neon/intrinsics
|
//! [arm_dat]: https://developer.arm.com/technologies/neon/intrinsics
|
||||||
|
|
||||||
mod armclang;
|
|
||||||
pub use self::armclang::*;
|
|
||||||
|
|
||||||
mod v6;
|
|
||||||
pub use self::v6::*;
|
|
||||||
|
|
||||||
// Supported arches: 6, 7-M. See Section 10.1 of ACLE (e.g. SSAT)
|
// Supported arches: 6, 7-M. See Section 10.1 of ACLE (e.g. SSAT)
|
||||||
#[cfg(any(target_feature = "v6", doc))]
|
#[cfg(any(target_feature = "v6", doc))]
|
||||||
mod sat;
|
mod sat;
|
||||||
@@ -62,14 +56,6 @@ mod simd32;
|
|||||||
))]
|
))]
|
||||||
pub use self::simd32::*;
|
pub use self::simd32::*;
|
||||||
|
|
||||||
#[cfg(any(target_feature = "v7", doc))]
|
|
||||||
mod v7;
|
|
||||||
#[cfg(any(target_feature = "v7", doc))]
|
|
||||||
pub use self::v7::*;
|
|
||||||
|
|
||||||
mod ex;
|
|
||||||
pub use self::ex::*;
|
|
||||||
|
|
||||||
pub use crate::core_arch::arm_shared::*;
|
pub use crate::core_arch::arm_shared::*;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@@ -1,49 +0,0 @@
|
|||||||
//! ARMv6 intrinsics.
|
|
||||||
//!
|
|
||||||
//! The reference is [ARMv6-M Architecture Reference Manual][armv6m].
|
|
||||||
//!
|
|
||||||
//! [armv6m]:
|
|
||||||
//! http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0419c/index.
|
|
||||||
//! html
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
use stdarch_test::assert_instr;
|
|
||||||
|
|
||||||
/// Reverse the order of the bytes.
|
|
||||||
#[inline]
|
|
||||||
#[cfg_attr(test, assert_instr(rev))]
|
|
||||||
pub unsafe fn _rev_u16(x: u16) -> u16 {
|
|
||||||
x.swap_bytes() as u16
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reverse the order of the bytes.
|
|
||||||
#[inline]
|
|
||||||
#[cfg_attr(test, assert_instr(rev))]
|
|
||||||
pub unsafe fn _rev_u32(x: u32) -> u32 {
|
|
||||||
x.swap_bytes() as u32
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::core_arch::arm::v6;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn _rev_u16() {
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(
|
|
||||||
v6::_rev_u16(0b0000_0000_1111_1111_u16),
|
|
||||||
0b1111_1111_0000_0000_u16
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn _rev_u32() {
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(
|
|
||||||
v6::_rev_u32(0b0000_0000_1111_1111_0000_0000_1111_1111_u32),
|
|
||||||
0b1111_1111_0000_0000_1111_1111_0000_0000_u32
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
//! ARMv7 intrinsics.
|
|
||||||
//!
|
|
||||||
//! The reference is [ARMv7-M Architecture Reference Manual (Issue
|
|
||||||
//! E.b)][armv7m].
|
|
||||||
//!
|
|
||||||
//! [armv7m]:
|
|
||||||
//! http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0403e.
|
|
||||||
//! b/index.html
|
|
||||||
|
|
||||||
pub use super::v6::*;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
use stdarch_test::assert_instr;
|
|
||||||
|
|
||||||
/// Count Leading Zeros.
|
|
||||||
#[inline]
|
|
||||||
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
|
|
||||||
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
|
|
||||||
// FIXME: https://github.com/rust-lang/stdarch/issues/382
|
|
||||||
// #[cfg_attr(all(test, target_arch = "arm"), assert_instr(clz))]
|
|
||||||
pub unsafe fn _clz_u8(x: u8) -> u8 {
|
|
||||||
x.leading_zeros() as u8
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Count Leading Zeros.
|
|
||||||
#[inline]
|
|
||||||
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
|
|
||||||
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
|
|
||||||
// FIXME: https://github.com/rust-lang/stdarch/issues/382
|
|
||||||
// #[cfg_attr(all(test, target_arch = "arm"), assert_instr(clz))]
|
|
||||||
pub unsafe fn _clz_u16(x: u16) -> u16 {
|
|
||||||
x.leading_zeros() as u16
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Count Leading Zeros.
|
|
||||||
#[inline]
|
|
||||||
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
|
|
||||||
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(clz))]
|
|
||||||
// FIXME: https://github.com/rust-lang/stdarch/issues/382
|
|
||||||
// #[cfg_attr(all(test, target_arch = "arm"), assert_instr(clz))]
|
|
||||||
pub unsafe fn _clz_u32(x: u32) -> u32 {
|
|
||||||
x.leading_zeros() as u32
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reverse the bit order.
|
|
||||||
#[inline]
|
|
||||||
#[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))]
|
|
||||||
#[cfg_attr(test, assert_instr(rbit))]
|
|
||||||
pub unsafe fn _rbit_u32(x: u32) -> u32 {
|
|
||||||
crate::intrinsics::bitreverse(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::core_arch::arm::v7;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn _clz_u8() {
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(v7::_clz_u8(0b0000_1010u8), 4u8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn _clz_u16() {
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(v7::_clz_u16(0b0000_1010u16), 12u16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn _clz_u32() {
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(v7::_clz_u32(0b0000_1010u32), 28u32);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn _rbit_u32() {
|
|
||||||
unsafe {
|
|
||||||
assert_eq!(
|
|
||||||
v7::_rbit_u32(0b0000_1010u32),
|
|
||||||
0b0101_0000_0000_0000_0000_0000_0000_0000u32
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -59,9 +59,6 @@ pub use self::barrier::*;
|
|||||||
mod hints;
|
mod hints;
|
||||||
pub use self::hints::*;
|
pub use self::hints::*;
|
||||||
|
|
||||||
mod registers;
|
|
||||||
pub use self::registers::*;
|
|
||||||
|
|
||||||
#[cfg(any(target_arch = "aarch64", target_feature = "v7", doc))]
|
#[cfg(any(target_arch = "aarch64", target_feature = "v7", doc))]
|
||||||
mod crc;
|
mod crc;
|
||||||
#[cfg(any(target_arch = "aarch64", target_feature = "v7", doc))]
|
#[cfg(any(target_arch = "aarch64", target_feature = "v7", doc))]
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
/// Application Program Status Register
|
|
||||||
pub struct APSR;
|
|
||||||
|
|
||||||
// Note (@Lokathor): Because this breaks the use of Rust on the Game Boy
|
|
||||||
// Advance, this change must be reverted until Rust learns to handle cpu state
|
|
||||||
// properly. See also: https://github.com/rust-lang/stdarch/issues/702
|
|
||||||
|
|
||||||
//#[cfg(any(not(target_feature = "thumb-state"), target_feature = "v6t2"))]
|
|
||||||
//rsr!(APSR);
|
|
||||||
@@ -1,121 +0,0 @@
|
|||||||
#[allow(unused_macros)]
|
|
||||||
macro_rules! rsr {
|
|
||||||
($R:ident) => {
|
|
||||||
impl super::super::sealed::Rsr for $R {
|
|
||||||
unsafe fn __rsr(&self) -> u32 {
|
|
||||||
let r: u32;
|
|
||||||
crate::arch::asm!(concat!("mrs {},", stringify!($R)), out(reg) r, options(nomem, nostack));
|
|
||||||
r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_macros)]
|
|
||||||
macro_rules! rsrp {
|
|
||||||
($R:ident) => {
|
|
||||||
impl super::super::sealed::Rsrp for $R {
|
|
||||||
unsafe fn __rsrp(&self) -> *const u8 {
|
|
||||||
let r: *const u8;
|
|
||||||
crate::arch::asm!(concat!("mrs {},", stringify!($R)), out(reg) r, options(nomem, nostack));
|
|
||||||
r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_macros)]
|
|
||||||
macro_rules! wsr {
|
|
||||||
($R:ident) => {
|
|
||||||
impl super::super::sealed::Wsr for $R {
|
|
||||||
unsafe fn __wsr(&self, value: u32) {
|
|
||||||
crate::arch::asm!(concat!("msr ", stringify!($R), ", {}"), in(reg) value, options(nomem, nostack));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unused_macros)]
|
|
||||||
macro_rules! wsrp {
|
|
||||||
($R:ident) => {
|
|
||||||
impl super::super::sealed::Wsrp for $R {
|
|
||||||
unsafe fn __wsrp(&self, value: *const u8) {
|
|
||||||
crate::arch::asm!(concat!("msr ", stringify!($R), ", {}"), in(reg) value, options(nomem, nostack));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(target_feature = "mclass")]
|
|
||||||
mod v6m;
|
|
||||||
|
|
||||||
#[cfg(target_feature = "mclass")]
|
|
||||||
pub use self::v6m::*;
|
|
||||||
|
|
||||||
#[cfg(all(target_feature = "v7", target_feature = "mclass"))]
|
|
||||||
mod v7m;
|
|
||||||
|
|
||||||
#[cfg(all(target_feature = "v7", target_feature = "mclass"))]
|
|
||||||
pub use self::v7m::*;
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "aarch64"))]
|
|
||||||
mod aarch32;
|
|
||||||
|
|
||||||
#[cfg(not(target_arch = "aarch64"))]
|
|
||||||
pub use self::aarch32::*;
|
|
||||||
|
|
||||||
/// Reads a 32-bit system register
|
|
||||||
#[inline(always)]
|
|
||||||
pub unsafe fn __rsr<R>(reg: R) -> u32
|
|
||||||
where
|
|
||||||
R: super::sealed::Rsr,
|
|
||||||
{
|
|
||||||
reg.__rsr()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reads a 64-bit system register
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
#[inline(always)]
|
|
||||||
pub unsafe fn __rsr64<R>(reg: R) -> u64
|
|
||||||
where
|
|
||||||
R: super::sealed::Rsr64,
|
|
||||||
{
|
|
||||||
reg.__rsr64()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reads a system register containing an address
|
|
||||||
#[inline(always)]
|
|
||||||
pub unsafe fn __rsrp<R>(reg: R) -> *const u8
|
|
||||||
where
|
|
||||||
R: super::sealed::Rsrp,
|
|
||||||
{
|
|
||||||
reg.__rsrp()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes a 32-bit system register
|
|
||||||
#[inline(always)]
|
|
||||||
pub unsafe fn __wsr<R>(reg: R, value: u32)
|
|
||||||
where
|
|
||||||
R: super::sealed::Wsr,
|
|
||||||
{
|
|
||||||
reg.__wsr(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes a 64-bit system register
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
|
||||||
#[inline(always)]
|
|
||||||
pub unsafe fn __wsr64<R>(reg: R, value: u64)
|
|
||||||
where
|
|
||||||
R: super::sealed::Wsr64,
|
|
||||||
{
|
|
||||||
reg.__wsr64(value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Writes a system register containing an address
|
|
||||||
#[inline(always)]
|
|
||||||
pub unsafe fn __wsrp<R>(reg: R, value: *const u8)
|
|
||||||
where
|
|
||||||
R: super::sealed::Wsrp,
|
|
||||||
{
|
|
||||||
reg.__wsrp(value)
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
/// CONTROL register
|
|
||||||
pub struct CONTROL;
|
|
||||||
|
|
||||||
rsr!(CONTROL);
|
|
||||||
wsr!(CONTROL);
|
|
||||||
|
|
||||||
/// Execution Program Status Register
|
|
||||||
pub struct EPSR;
|
|
||||||
|
|
||||||
rsr!(EPSR);
|
|
||||||
|
|
||||||
/// Interrupt Program Status Register
|
|
||||||
pub struct IPSR;
|
|
||||||
|
|
||||||
rsr!(IPSR);
|
|
||||||
|
|
||||||
/// Main Stack Pointer
|
|
||||||
pub struct MSP;
|
|
||||||
|
|
||||||
rsrp!(MSP);
|
|
||||||
wsrp!(MSP);
|
|
||||||
|
|
||||||
/// Priority Mask Register
|
|
||||||
pub struct PRIMASK;
|
|
||||||
|
|
||||||
rsr!(PRIMASK);
|
|
||||||
wsr!(PRIMASK);
|
|
||||||
|
|
||||||
/// Process Stack Pointer
|
|
||||||
pub struct PSP;
|
|
||||||
|
|
||||||
rsrp!(PSP);
|
|
||||||
wsrp!(PSP);
|
|
||||||
|
|
||||||
/// Program Status Register
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
pub struct xPSR;
|
|
||||||
|
|
||||||
rsr!(xPSR);
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
/// Base Priority Mask Register
|
|
||||||
pub struct BASEPRI;
|
|
||||||
|
|
||||||
rsr!(BASEPRI);
|
|
||||||
wsr!(BASEPRI);
|
|
||||||
|
|
||||||
/// Base Priority Mask Register (conditional write)
|
|
||||||
#[allow(non_camel_case_types)]
|
|
||||||
pub struct BASEPRI_MAX;
|
|
||||||
|
|
||||||
wsr!(BASEPRI_MAX);
|
|
||||||
|
|
||||||
/// Fault Mask Register
|
|
||||||
pub struct FAULTMASK;
|
|
||||||
|
|
||||||
rsr!(FAULTMASK);
|
|
||||||
wsr!(FAULTMASK);
|
|
||||||
Reference in New Issue
Block a user