Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert all uses of llvm_asm! to asm! #1052

Merged
merged 1 commit into from
Mar 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions crates/core_arch/src/acle/barrier/cp15.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,29 @@ pub struct SY;
impl super::super::sealed::Dmb for SY {
#[inline(always)]
unsafe fn __dmb(&self) {
llvm_asm!("mcr p15, 0, r0, c7, c10, 5" : : : "memory" : "volatile")
asm!(
"mcr p15, 0, r0, c7, c10, 5",
options(preserves_flags, nostack)
)
}
}

impl super::super::sealed::Dsb for SY {
#[inline(always)]
unsafe fn __dsb(&self) {
llvm_asm!("mcr p15, 0, r0, c7, c10, 4" : : : "memory" : "volatile")
asm!(
"mcr p15, 0, r0, c7, c10, 4",
options(preserves_flags, nostack)
)
}
}

impl super::super::sealed::Isb for SY {
#[inline(always)]
unsafe fn __isb(&self) {
llvm_asm!("mcr p15, 0, r0, c7, c5, 4" : : : "memory" : "volatile")
asm!(
"mcr p15, 0, r0, c7, c5, 4",
options(preserves_flags, nostack)
)
}
}
38 changes: 11 additions & 27 deletions crates/core_arch/src/acle/hints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,33 +80,13 @@ pub unsafe fn __yield() {
// and ARMv7-R edition (ARM DDI 0406C.c) sections D12.4.1 "ARM instruction set support" and D12.4.2
// "Thumb instruction set support"
#[cfg(target_feature = "v7")]
#[cfg(any(target_arch = "arm", doc))]
#[doc(cfg(target_arch = "arm"))]
#[inline(always)]
#[rustc_args_required_const(0)]
pub unsafe fn __dbg(imm4: u32) {
macro_rules! call {
($imm4:expr) => {
llvm_asm!(concat!("DBG ", stringify!($imm4)) : : : : "volatile")
}
}

match imm4 & 0b1111 {
0 => call!(0),
1 => call!(1),
2 => call!(2),
3 => call!(3),
4 => call!(4),
5 => call!(5),
6 => call!(6),
7 => call!(7),
8 => call!(8),
9 => call!(9),
10 => call!(10),
11 => call!(11),
12 => call!(12),
13 => call!(13),
14 => call!(14),
_ => call!(15),
}
#[rustc_legacy_const_generics(0)]
pub unsafe fn __dbg<const IMM4: i32>() {
static_assert_imm4!(IMM4);
dbg(IMM4);
}

/// Generates an unspecified no-op instruction.
Expand All @@ -117,13 +97,17 @@ pub unsafe fn __dbg(imm4: u32) {
/// will increase execution time.
#[inline(always)]
pub unsafe fn __nop() {
llvm_asm!("NOP" : : : : "volatile")
asm!("nop", options(nomem, nostack, preserves_flags));
}

extern "C" {
#[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.hint")]
#[cfg_attr(target_arch = "arm", link_name = "llvm.arm.hint")]
fn hint(_: i32);

#[cfg(target_arch = "arm")]
#[link_name = "llvm.arm.dbg"]
fn dbg(_: i32);
}

// from LLVM 7.0.1's lib/Target/ARM/{ARMInstrThumb,ARMInstrInfo,ARMInstrThumb2}.td
Expand Down
8 changes: 4 additions & 4 deletions crates/core_arch/src/acle/registers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ macro_rules! rsr {
impl super::super::sealed::Rsr for $R {
unsafe fn __rsr(&self) -> u32 {
let r: u32;
llvm_asm!(concat!("mrs $0,", stringify!($R)) : "=r"(r) : : : "volatile");
asm!(concat!("mrs {},", stringify!($R)), out(reg) r, options(nomem, nostack));
r
}
}
Expand All @@ -17,7 +17,7 @@ macro_rules! rsrp {
impl super::super::sealed::Rsrp for $R {
unsafe fn __rsrp(&self) -> *const u8 {
let r: *const u8;
llvm_asm!(concat!("mrs $0,", stringify!($R)) : "=r"(r) : : : "volatile");
asm!(concat!("mrs {},", stringify!($R)), out(reg) r, options(nomem, nostack));
r
}
}
Expand All @@ -29,7 +29,7 @@ macro_rules! wsr {
($R:ident) => {
impl super::super::sealed::Wsr for $R {
unsafe fn __wsr(&self, value: u32) {
llvm_asm!(concat!("msr ", stringify!($R), ",$0") : : "r"(value) : : "volatile");
asm!(concat!("msr ", stringify!($R), ", {}"), in(reg) value, options(nomem, nostack));
}
}
};
Expand All @@ -40,7 +40,7 @@ macro_rules! wsrp {
($R:ident) => {
impl super::super::sealed::Wsrp for $R {
unsafe fn __wsrp(&self, value: *const u8) {
llvm_asm!(concat!("msr ", stringify!($R), ",$0") : : "r"(value) : : "volatile");
asm!(concat!("msr ", stringify!($R), ", {}"), in(reg) value, options(nomem, nostack));
}
}
};
Expand Down
65 changes: 24 additions & 41 deletions crates/core_arch/src/arm/armclang.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,58 +11,41 @@ use stdarch_test::assert_instr;

/// Inserts a breakpoint instruction.
///
/// `val` is a compile-time constant integer in range `[0, 255]`.
/// `VAL` is a compile-time constant integer in range `[0, 65535]`.
///
/// The breakpoint instruction inserted is:
///
/// * `BKPT` when compiling as T32,
/// * `BRK` when compiling as A32 or A64.
/// The breakpoint instruction inserted is `BRK` on A64.
#[cfg(all(target_arch = "aarch64", not(doc)))]
#[cfg_attr(test, assert_instr(brk, VAL = 0))]
#[inline(always)]
#[rustc_legacy_const_generics(0)]
pub unsafe fn __breakpoint<const VAL: i32>() {
static_assert_imm16!(VAL);
asm!("brk {}", const VAL);
}

/// Inserts a breakpoint instruction.
///
/// # Safety
/// `VAL` is a compile-time constant integer in range `[0, 255]`.
///
/// If `val` is out-of-range the behavior is **undefined**.
/// The breakpoint instruction inserted is `BKPT` on A32/T32.
///
/// # Note
///
/// [ARM's documentation][arm_docs] defines that `__breakpoint` accepts the
/// following values for `val`:
/// following values for `VAL`:
///
/// - `0...65535` when compiling as A32 or A64,
/// - `0...65535` when compiling as A32,
/// - `0...255` when compiling as T32.
///
/// The current implementation only accepts values in range `[0, 255]` - if the
/// value is out-of-range the behavior is **undefined**.
/// 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(all(test, target_arch = "arm"), assert_instr(bkpt, val = 0))]
#[cfg_attr(all(test, target_arch = "aarch64"), assert_instr(brk, val = 0))]
#[cfg(any(target_arch = "arm", doc))]
#[doc(cfg(target_arch = "arm"))]
#[cfg_attr(test, assert_instr(bkpt, VAL = 0))]
#[inline(always)]
#[rustc_args_required_const(0)]
pub unsafe fn __breakpoint(val: i32) {
// Ensure that this compiles correctly on non-arm architectures, so libstd
// doc builds work. The proper macro will shadow this definition below.
#[allow(unused_macros)]
macro_rules! call {
($e:expr) => {
()
};
}

#[cfg(target_arch = "arm")]
macro_rules! call {
($imm8:expr) => {
llvm_asm!(concat!("BKPT ", stringify!($imm8)) : : : : "volatile")
}
}

#[cfg(target_arch = "aarch64")]
macro_rules! call {
($imm8:expr) => {
llvm_asm!(concat!("BRK ", stringify!($imm8)) : : : : "volatile")
}
}

// We can't `panic!` inside this intrinsic, so we can't really validate the
// arguments here. If `val` is out-of-range this macro uses `val == 255`:
constify_imm8!(val, call);
#[rustc_legacy_const_generics(0)]
pub unsafe fn __breakpoint<const VAL: i32>() {
static_assert_imm8!(VAL);
asm!("bkpt #{}", const VAL);
}
1 change: 0 additions & 1 deletion crates/core_arch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
platform_intrinsics,
repr_simd,
simd_ffi,
llvm_asm,
proc_macro_hygiene,
stmt_expr_attributes,
core_intrinsics,
Expand Down
7 changes: 7 additions & 0 deletions crates/core_arch/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ macro_rules! static_assert_imm8 {
};
}

#[allow(unused_macros)]
macro_rules! static_assert_imm16 {
($imm:ident) => {
let _ = $crate::core_arch::macros::ValidateConstImm::<$imm, 0, { (1 << 16) - 1 }>::VALID;
};
}

#[allow(unused)]
macro_rules! static_assert {
($imm:ident : $ty:ty where $e:expr) => {
Expand Down
48 changes: 32 additions & 16 deletions crates/core_arch/src/x86/bt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@ use stdarch_test::assert_instr;
#[unstable(feature = "simd_x86_bittest", issue = "59414")]
pub unsafe fn _bittest(p: *const i32, b: i32) -> u8 {
let r: u8;
llvm_asm!("btl $2, $1\n\tsetc ${0:b}"
: "=r"(r)
: "*m"(p), "r"(b)
: "cc", "memory");
asm!(
"bt [{p}], {b:e}",
"setc {r}",
p = in(reg) p,
b = in(reg) b,
r = out(reg_byte) r,
options(readonly, nostack, pure)
);
r
}

Expand All @@ -20,10 +24,14 @@ pub unsafe fn _bittest(p: *const i32, b: i32) -> u8 {
#[unstable(feature = "simd_x86_bittest", issue = "59414")]
pub unsafe fn _bittestandset(p: *mut i32, b: i32) -> u8 {
let r: u8;
llvm_asm!("btsl $2, $1\n\tsetc ${0:b}"
: "=r"(r), "+*m"(p)
: "r"(b)
: "cc", "memory");
asm!(
"bts [{p}], {b:e}",
"setc {r}",
p = in(reg) p,
b = in(reg) b,
r = out(reg_byte) r,
options(nostack)
);
r
}

Expand All @@ -33,10 +41,14 @@ pub unsafe fn _bittestandset(p: *mut i32, b: i32) -> u8 {
#[unstable(feature = "simd_x86_bittest", issue = "59414")]
pub unsafe fn _bittestandreset(p: *mut i32, b: i32) -> u8 {
let r: u8;
llvm_asm!("btrl $2, $1\n\tsetc ${0:b}"
: "=r"(r), "+*m"(p)
: "r"(b)
: "cc", "memory");
asm!(
"btr [{p}], {b:e}",
"setc {r}",
p = in(reg) p,
b = in(reg) b,
r = out(reg_byte) r,
options(nostack)
);
r
}

Expand All @@ -46,10 +58,14 @@ pub unsafe fn _bittestandreset(p: *mut i32, b: i32) -> u8 {
#[unstable(feature = "simd_x86_bittest", issue = "59414")]
pub unsafe fn _bittestandcomplement(p: *mut i32, b: i32) -> u8 {
let r: u8;
llvm_asm!("btcl $2, $1\n\tsetc ${0:b}"
: "=r"(r), "+*m"(p)
: "r"(b)
: "cc", "memory");
asm!(
"btc [{p}], {b:e}",
"setc {r}",
p = in(reg) p,
b = in(reg) b,
r = out(reg_byte) r,
options(nostack)
);
r
}

Expand Down
43 changes: 19 additions & 24 deletions crates/core_arch/src/x86/cpuid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,30 +125,25 @@ pub fn has_cpuid() -> bool {
// the 21st bit of the EFLAGS register is modifiable or not.
// If it is, then `cpuid` is available.
let result: u32;
let _temp: u32;
llvm_asm!(r#"
# Read eflags into $0 and copy it into $1:
pushfd
pop $0
mov $1, $0
# Flip 21st bit of $0.
xor $0, 0x200000
# Set eflags to the value of $0
#
# Bit 21st can only be modified if cpuid is available
push $0
popfd # A
# Read eflags into $0:
pushfd # B
pop $0
# xor with the original eflags sets the bits that
# have been modified:
xor $0, $1
"#
: "=r"(result), "=r"(_temp)
:
: "cc", "memory"
: "intel");
asm!(
// Read eflags and save a copy of it
"pushfd",
"pop {result}",
"mov {saved_flags}, {result}",
// Flip 21st bit of the flags
"xor {result}, 0x200000",
// Load the modified flags and read them back.
// Bit 21 can only be modified if cpuid is available.
"push {result}",
"popfd",
"pushfd",
"pop {result}",
// Use xor to find out whether bit 21 has changed
"xor {result}, {saved_flags}",
result = out(reg) result,
saved_flags = out(reg) _,
options(nomem),
);
// There is a race between popfd (A) and pushfd (B)
// where other bits beyond 21st may have been modified due to
// interrupts, a debugger stepping through the asm, etc.
Expand Down
8 changes: 4 additions & 4 deletions crates/core_arch/src/x86/eflags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
#[doc(hidden)]
pub unsafe fn __readeflags() -> u32 {
let eflags: u32;
llvm_asm!("pushfd; popl $0" : "=r"(eflags) : : : "volatile");
asm!("pushfd", "pop {}", out(reg) eflags, options(nomem));
eflags
}

Expand All @@ -30,7 +30,7 @@ pub unsafe fn __readeflags() -> u32 {
#[doc(hidden)]
pub unsafe fn __readeflags() -> u64 {
let eflags: u64;
llvm_asm!("pushfq; popq $0" : "=r"(eflags) : : : "volatile");
asm!("pushfq", "pop {}", out(reg) eflags, options(nomem));
eflags
}

Expand All @@ -46,7 +46,7 @@ pub unsafe fn __readeflags() -> u64 {
)]
#[doc(hidden)]
pub unsafe fn __writeeflags(eflags: u32) {
llvm_asm!("pushl $0; popfd" : : "r"(eflags) : "cc", "flags" : "volatile");
asm!("push {}", "popfd", in(reg) eflags, options(nomem));
}

/// Write EFLAGS.
Expand All @@ -61,7 +61,7 @@ pub unsafe fn __writeeflags(eflags: u32) {
)]
#[doc(hidden)]
pub unsafe fn __writeeflags(eflags: u64) {
llvm_asm!("pushq $0; popfq" : : "r"(eflags) : "cc", "flags" : "volatile");
asm!("push {}", "popfq", in(reg) eflags, options(nomem));
}

#[cfg(test)]
Expand Down
Loading