aboutsummaryrefslogtreecommitdiff
path: root/vendor/portable-atomic/src/imp/x86.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/portable-atomic/src/imp/x86.rs')
-rw-r--r--vendor/portable-atomic/src/imp/x86.rs227
1 files changed, 0 insertions, 227 deletions
diff --git a/vendor/portable-atomic/src/imp/x86.rs b/vendor/portable-atomic/src/imp/x86.rs
deleted file mode 100644
index 9ef4d74..0000000
--- a/vendor/portable-atomic/src/imp/x86.rs
+++ /dev/null
@@ -1,227 +0,0 @@
-// SPDX-License-Identifier: Apache-2.0 OR MIT
-
-// Atomic operations implementation on x86/x86_64.
-//
-// This module provides atomic operations not supported by LLVM or optimizes
-// cases where LLVM code generation is not optimal.
-//
-// Note: On Miri and ThreadSanitizer which do not support inline assembly, we don't use
-// this module and use CAS loop instead.
-//
-// Refs:
-// - x86 and amd64 instruction reference https://www.felixcloutier.com/x86
-//
-// Generated asm:
-// - x86_64 https://godbolt.org/z/d17eTs5Ec
-
-use core::{arch::asm, sync::atomic::Ordering};
-
-use super::core_atomic::{
- AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU64,
- AtomicU8, AtomicUsize,
-};
-
-#[cfg(target_pointer_width = "32")]
-macro_rules! ptr_modifier {
- () => {
- ":e"
- };
-}
-#[cfg(target_pointer_width = "64")]
-macro_rules! ptr_modifier {
- () => {
- ""
- };
-}
-
-macro_rules! atomic_int {
- ($atomic_type:ident, $ptr_size:tt) => {
- impl $atomic_type {
- #[inline]
- pub(crate) fn not(&self, _order: Ordering) {
- let dst = self.as_ptr();
- // SAFETY: any data races are prevented by atomic intrinsics and the raw
- // pointer passed in is valid because we got it from a reference.
- //
- // https://www.felixcloutier.com/x86/not
- unsafe {
- // atomic RMW is always SeqCst.
- asm!(
- concat!("lock not ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}]"),
- dst = in(reg) dst,
- options(nostack, preserves_flags),
- );
- }
- }
- #[inline]
- pub(crate) fn neg(&self, _order: Ordering) {
- let dst = self.as_ptr();
- // SAFETY: any data races are prevented by atomic intrinsics and the raw
- // pointer passed in is valid because we got it from a reference.
- //
- // https://www.felixcloutier.com/x86/neg
- unsafe {
- // atomic RMW is always SeqCst.
- asm!(
- concat!("lock neg ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}]"),
- dst = in(reg) dst,
- // Do not use `preserves_flags` because NEG modifies the CF, OF, SF, ZF, AF, and PF flag.
- options(nostack),
- );
- }
- }
- }
- };
-}
-
-atomic_int!(AtomicI8, "byte");
-atomic_int!(AtomicU8, "byte");
-atomic_int!(AtomicI16, "word");
-atomic_int!(AtomicU16, "word");
-atomic_int!(AtomicI32, "dword");
-atomic_int!(AtomicU32, "dword");
-#[cfg(target_arch = "x86_64")]
-atomic_int!(AtomicI64, "qword");
-#[cfg(target_arch = "x86_64")]
-atomic_int!(AtomicU64, "qword");
-#[cfg(target_pointer_width = "32")]
-atomic_int!(AtomicIsize, "dword");
-#[cfg(target_pointer_width = "32")]
-atomic_int!(AtomicUsize, "dword");
-#[cfg(target_pointer_width = "64")]
-atomic_int!(AtomicIsize, "qword");
-#[cfg(target_pointer_width = "64")]
-atomic_int!(AtomicUsize, "qword");
-
-#[cfg(target_arch = "x86")]
-impl AtomicI64 {
- #[inline]
- pub(crate) fn not(&self, order: Ordering) {
- self.fetch_not(order);
- }
- #[inline]
- pub(crate) fn neg(&self, order: Ordering) {
- self.fetch_neg(order);
- }
-}
-#[cfg(target_arch = "x86")]
-impl AtomicU64 {
- #[inline]
- pub(crate) fn not(&self, order: Ordering) {
- self.fetch_not(order);
- }
- #[inline]
- pub(crate) fn neg(&self, order: Ordering) {
- self.fetch_neg(order);
- }
-}
-
-macro_rules! atomic_bit_opts {
- ($atomic_type:ident, $int_type:ident, $val_modifier:tt, $ptr_size:tt) => {
- // LLVM 14 and older don't support generating `lock bt{s,r,c}`.
- // LLVM 15 only supports generating `lock bt{s,r,c}` for immediate bit offsets.
- // LLVM 16+ can generate `lock bt{s,r,c}` for both immediate and register bit offsets.
- // https://godbolt.org/z/TGhr5z4ds
- // So, use fetch_* based implementations on LLVM 16+, otherwise use asm based implementations.
- #[cfg(portable_atomic_llvm_16)]
- impl_default_bit_opts!($atomic_type, $int_type);
- #[cfg(not(portable_atomic_llvm_16))]
- impl $atomic_type {
- #[inline]
- pub(crate) fn bit_set(&self, bit: u32, _order: Ordering) -> bool {
- let dst = self.as_ptr();
- // SAFETY: any data races are prevented by atomic intrinsics and the raw
- // pointer passed in is valid because we got it from a reference.
- // the masking by the bit size of the type ensures that we do not shift
- // out of bounds.
- //
- // https://www.felixcloutier.com/x86/bts
- unsafe {
- let r: u8;
- // atomic RMW is always SeqCst.
- asm!(
- concat!("lock bts ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}], {bit", $val_modifier, "}"),
- "setb {r}",
- dst = in(reg) dst,
- bit = in(reg) (bit & ($int_type::BITS - 1)) as $int_type,
- r = out(reg_byte) r,
- // Do not use `preserves_flags` because BTS modifies the CF flag.
- options(nostack),
- );
- r != 0
- }
- }
- #[inline]
- pub(crate) fn bit_clear(&self, bit: u32, _order: Ordering) -> bool {
- let dst = self.as_ptr();
- // SAFETY: any data races are prevented by atomic intrinsics and the raw
- // pointer passed in is valid because we got it from a reference.
- // the masking by the bit size of the type ensures that we do not shift
- // out of bounds.
- //
- // https://www.felixcloutier.com/x86/btr
- unsafe {
- let r: u8;
- // atomic RMW is always SeqCst.
- asm!(
- concat!("lock btr ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}], {bit", $val_modifier, "}"),
- "setb {r}",
- dst = in(reg) dst,
- bit = in(reg) (bit & ($int_type::BITS - 1)) as $int_type,
- r = out(reg_byte) r,
- // Do not use `preserves_flags` because BTR modifies the CF flag.
- options(nostack),
- );
- r != 0
- }
- }
- #[inline]
- pub(crate) fn bit_toggle(&self, bit: u32, _order: Ordering) -> bool {
- let dst = self.as_ptr();
- // SAFETY: any data races are prevented by atomic intrinsics and the raw
- // pointer passed in is valid because we got it from a reference.
- // the masking by the bit size of the type ensures that we do not shift
- // out of bounds.
- //
- // https://www.felixcloutier.com/x86/btc
- unsafe {
- let r: u8;
- // atomic RMW is always SeqCst.
- asm!(
- concat!("lock btc ", $ptr_size, " ptr [{dst", ptr_modifier!(), "}], {bit", $val_modifier, "}"),
- "setb {r}",
- dst = in(reg) dst,
- bit = in(reg) (bit & ($int_type::BITS - 1)) as $int_type,
- r = out(reg_byte) r,
- // Do not use `preserves_flags` because BTC modifies the CF flag.
- options(nostack),
- );
- r != 0
- }
- }
- }
- };
-}
-
-impl_default_bit_opts!(AtomicI8, i8);
-impl_default_bit_opts!(AtomicU8, u8);
-atomic_bit_opts!(AtomicI16, i16, ":x", "word");
-atomic_bit_opts!(AtomicU16, u16, ":x", "word");
-atomic_bit_opts!(AtomicI32, i32, ":e", "dword");
-atomic_bit_opts!(AtomicU32, u32, ":e", "dword");
-#[cfg(target_arch = "x86_64")]
-atomic_bit_opts!(AtomicI64, i64, "", "qword");
-#[cfg(target_arch = "x86_64")]
-atomic_bit_opts!(AtomicU64, u64, "", "qword");
-#[cfg(target_arch = "x86")]
-impl_default_bit_opts!(AtomicI64, i64);
-#[cfg(target_arch = "x86")]
-impl_default_bit_opts!(AtomicU64, u64);
-#[cfg(target_pointer_width = "32")]
-atomic_bit_opts!(AtomicIsize, isize, ":e", "dword");
-#[cfg(target_pointer_width = "32")]
-atomic_bit_opts!(AtomicUsize, usize, ":e", "dword");
-#[cfg(target_pointer_width = "64")]
-atomic_bit_opts!(AtomicIsize, isize, "", "qword");
-#[cfg(target_pointer_width = "64")]
-atomic_bit_opts!(AtomicUsize, usize, "", "qword");