about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2025-01-29 12:16:51 +0100
committerRalf Jung <post@ralfj.de>2025-02-14 19:47:52 +0100
commit2eff2155e5467c42f43143f282dd96f9ccb7bf08 (patch)
tree56382ec9b9d1093c345ea1d0178df58e7c027661
parentbdc97d104696f6abccea657f76401e282fc6ca85 (diff)
downloadrust-2eff2155e5467c42f43143f282dd96f9ccb7bf08.tar.gz
rust-2eff2155e5467c42f43143f282dd96f9ccb7bf08.zip
add x86-sse2 (32bit) ABI that requires SSE2 target feature
-rw-r--r--compiler/rustc_target/src/spec/base/apple/mod.rs10
-rw-r--r--compiler/rustc_target/src/spec/mod.rs9
-rw-r--r--compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_linux_android.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs14
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs5
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs3
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs3
-rw-r--r--compiler/rustc_target/src/target_features.rs8
-rw-r--r--src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.stderr5
-rw-r--r--tests/ui/sse-abi-checks.rs2
-rw-r--r--tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs12
-rw-r--r--tests/ui/target-feature/target-cpu-lacks-required-target-feature.stderr7
25 files changed, 96 insertions, 20 deletions
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index 497994a5998..1b56143545f 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -2,8 +2,8 @@ use std::borrow::Cow;
 use std::env;
 
 use crate::spec::{
-    Cc, DebuginfoKind, FloatAbi, FramePointer, LinkerFlavor, Lld, SplitDebuginfo, StackProbeType,
-    StaticCow, TargetOptions, cvs,
+    Cc, DebuginfoKind, FloatAbi, FramePointer, LinkerFlavor, Lld, RustcAbi, SplitDebuginfo,
+    StackProbeType, StaticCow, TargetOptions, cvs,
 };
 
 #[cfg(test)]
@@ -103,7 +103,7 @@ pub(crate) fn base(
     arch: Arch,
     abi: TargetAbi,
 ) -> (TargetOptions, StaticCow<str>, StaticCow<str>) {
-    let opts = TargetOptions {
+    let mut opts = TargetOptions {
         abi: abi.target_abi().into(),
         llvm_floatabi: Some(FloatAbi::Hard),
         os: os.into(),
@@ -154,6 +154,10 @@ pub(crate) fn base(
 
         ..Default::default()
     };
+    if matches!(arch, Arch::I386 | Arch::I686) {
+        // All Apple x86-32 targets have SSE2.
+        opts.rustc_abi = Some(RustcAbi::X86Sse2);
+    }
     (opts, unversioned_llvm_target(os, arch, abi), arch.target_arch())
 }
 
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 8b20152d3bf..794d6457cb7 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1109,6 +1109,8 @@ impl ToJson for FloatAbi {
 /// The Rustc-specific variant of the ABI used for this target.
 #[derive(Clone, Copy, PartialEq, Hash, Debug)]
 pub enum RustcAbi {
+    /// On x86-32 only: make use of SSE and SSE2 for ABI purposes.
+    X86Sse2,
     /// On x86-32/64 only: do not use any FPU or SIMD registers for the ABI.
     X86Softfloat,
 }
@@ -1118,6 +1120,7 @@ impl FromStr for RustcAbi {
 
     fn from_str(s: &str) -> Result<RustcAbi, ()> {
         Ok(match s {
+            "x86-sse2" => RustcAbi::X86Sse2,
             "x86-softfloat" => RustcAbi::X86Softfloat,
             _ => return Err(()),
         })
@@ -1127,6 +1130,7 @@ impl FromStr for RustcAbi {
 impl ToJson for RustcAbi {
     fn to_json(&self) -> Json {
         match *self {
+            RustcAbi::X86Sse2 => "x86-sse2",
             RustcAbi::X86Softfloat => "x86-softfloat",
         }
         .to_json()
@@ -3264,6 +3268,11 @@ impl Target {
         // Check consistency of Rust ABI declaration.
         if let Some(rust_abi) = self.rustc_abi {
             match rust_abi {
+                RustcAbi::X86Sse2 => check_matches!(
+                    &*self.arch,
+                    "x86",
+                    "`x86-sse2` ABI is only valid for x86-32 targets"
+                ),
                 RustcAbi::X86Softfloat => check_matches!(
                     &*self.arch,
                     "x86" | "x86_64",
diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
index fa21cfbab8a..6a98a763b36 100644
--- a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
@@ -1,5 +1,5 @@
 use crate::spec::base::nto_qnx;
-use crate::spec::{StackProbeType, Target, TargetOptions, base};
+use crate::spec::{RustcAbi, StackProbeType, Target, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut meta = nto_qnx::meta();
@@ -14,6 +14,7 @@ pub(crate) fn target() -> Target {
             .into(),
         arch: "x86".into(),
         options: TargetOptions {
+            rustc_abi: Some(RustcAbi::X86Sse2),
             cpu: "pentium4".into(),
             max_atomic_width: Some(64),
             pre_link_args: nto_qnx::pre_link_args(
diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs
index e481e967ebf..f04e3c2c2a5 100644
--- a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_gnu.rs
@@ -2,6 +2,7 @@ use crate::spec::Target;
 
 pub(crate) fn target() -> Target {
     let mut base = super::i686_unknown_linux_gnu::target();
+    base.rustc_abi = None; // overwrite the SSE2 ABI set by the base target
     base.cpu = "pentium".into();
     base.llvm_target = "i586-unknown-linux-gnu".into();
     base
diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs
index 8ad93496f3a..42babb90da7 100644
--- a/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_unknown_linux_musl.rs
@@ -2,6 +2,7 @@ use crate::spec::Target;
 
 pub(crate) fn target() -> Target {
     let mut base = super::i686_unknown_linux_musl::target();
+    base.rustc_abi = None; // overwrite the SSE2 ABI set by the base target
     base.cpu = "pentium".into();
     base.llvm_target = "i586-unknown-linux-musl".into();
     // FIXME(compiler-team#422): musl targets should be dynamically linked by default.
diff --git a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
index 1b8f4c1be2d..7d61d5ca257 100644
--- a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
@@ -1,4 +1,4 @@
-use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{RustcAbi, SanitizerSet, StackProbeType, Target, TargetOptions, base};
 
 // See https://developer.android.com/ndk/guides/abis.html#x86
 // for target ABI requirements.
@@ -8,6 +8,7 @@ pub(crate) fn target() -> Target {
 
     base.max_atomic_width = Some(64);
 
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     // https://developer.android.com/ndk/guides/abis.html#x86
     base.cpu = "pentium4".into();
     base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".into();
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
index 208fe50912c..06dbf1e3a16 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnu::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.frame_pointer = FramePointer::Always; // Required for backtraces
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
index 5df8dce1aa3..05d848e0393 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnullvm::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.frame_pointer = FramePointer::Always; // Required for backtraces
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
index 180750bc7a8..e0e47113087 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
@@ -1,7 +1,8 @@
-use crate::spec::{LinkerFlavor, Lld, SanitizerSet, Target, base};
+use crate::spec::{LinkerFlavor, Lld, RustcAbi, SanitizerSet, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_msvc::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.supported_sanitizers = SanitizerSet::ADDRESS;
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
index 85ab87cc07f..71c26041a50 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::freebsd::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-znotext"]);
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
index 1ab493c787c..464ac46b07c 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::haiku::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
index c95cb308d7f..fe699dbcb51 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
@@ -1,7 +1,19 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, SanitizerSet, StackProbeType, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_gnu::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
+    // Dear distribution packager, if you are changing the base CPU model with the goal of removing
+    // the SSE2 requirement, make sure to also set the `rustc_abi` to `None` above or else the compiler
+    // will complain that the chosen ABI cannot be realized with the given CPU features.
+    // Also note that x86 without SSE2 is *not* considered a Tier 1 target by the Rust project, and
+    // it has some known floating-point correctness issues mostly caused by a lack of people caring
+    // for LLVM's x87 support (double-rounding, value truncation; see
+    // <https://github.com/rust-lang/rust/issues/114479> for details). This can lead to incorrect
+    // math (Rust generally promises exact math, so this can break code in unexpected ways) and it
+    // can lead to memory safety violations if floating-point values are used e.g. to access an
+    // array. If users run into such issues and report bugs upstream and then it turns out that the
+    // bugs are caused by distribution patches, that leads to confusion and frustration.
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.supported_sanitizers = SanitizerSet::ADDRESS;
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
index 6ba87c732b7..3d25c951e81 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
@@ -1,7 +1,10 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::linux_musl::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
+    // If you want to change the base CPU, please see `i686_unknown_linux_gnu.rs`
+    // for an important comment.
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-melf_i386"]);
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
index 092ba5c7baa..4bc6eee1ac2 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, TargetOptions, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::netbsd::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
index 7ae9189e233..a3bdf66a14d 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::openbsd::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-fuse-ld=lld"]);
diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
index 6e3733538ed..0e1b65ef598 100644
--- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_uwp_gnu::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.frame_pointer = FramePointer::Always; // Required for backtraces
diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
index e0de9b9af45..44cf9b1adda 100644
--- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Target, base};
+use crate::spec::{RustcAbi, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_uwp_msvc::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
 
diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
index 1d084c0729c..e9100da14cb 100644
--- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_gnu.rs
@@ -1,8 +1,9 @@
-use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base};
+use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_gnu::opts();
     base.vendor = "win7".into();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.frame_pointer = FramePointer::Always; // Required for backtraces
diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
index 7efba3aa986..94284a2fe72 100644
--- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
@@ -1,8 +1,9 @@
-use crate::spec::{LinkerFlavor, Lld, SanitizerSet, Target, base};
+use crate::spec::{LinkerFlavor, Lld, RustcAbi, SanitizerSet, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::windows_msvc::opts();
     base.vendor = "win7".into();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.supported_sanitizers = SanitizerSet::ADDRESS;
diff --git a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
index dfffa6e138f..4e801955d0c 100644
--- a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
@@ -1,7 +1,8 @@
-use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base};
+use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base};
 
 pub(crate) fn target() -> Target {
     let mut base = base::vxworks::opts();
+    base.rustc_abi = Some(RustcAbi::X86Sse2);
     base.cpu = "pentium4".into();
     base.max_atomic_width = Some(64);
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]);
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 1ba8defedae..bb41d03e87f 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -790,6 +790,13 @@ impl Target {
                         // x87 must be enabled, soft-float must be disabled.
                         FeatureConstraints { required: &["x87"], incompatible: &["soft-float"] }
                     }
+                    Some(RustcAbi::X86Sse2) => {
+                        // Extended hardfloat ABI. x87 and SSE2 must be enabled, soft-float must be disabled.
+                        FeatureConstraints {
+                            required: &["x87", "sse2"],
+                            incompatible: &["soft-float"],
+                        }
+                    }
                     Some(RustcAbi::X86Softfloat) => {
                         // Softfloat ABI, requires corresponding target feature. That feature trumps
                         // `x87` and all other FPU features so those do not matter.
@@ -817,6 +824,7 @@ impl Target {
                         // LLVM handles the rest.
                         FeatureConstraints { required: &["soft-float"], incompatible: &[] }
                     }
+                    Some(r) => panic!("invalid Rust ABI for x86_64: {r:?}"),
                 }
             }
             "arm" => {
diff --git a/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.stderr b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.stderr
new file mode 100644
index 00000000000..171bf0c82d5
--- /dev/null
+++ b/src/tools/miri/tests/pass/shims/x86/intrinsics-x86-pause-without-sse2.stderr
@@ -0,0 +1,5 @@
+warning: target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly
+   |
+   = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
+
diff --git a/tests/ui/sse-abi-checks.rs b/tests/ui/sse-abi-checks.rs
index c453e91d11b..d400e6eb698 100644
--- a/tests/ui/sse-abi-checks.rs
+++ b/tests/ui/sse-abi-checks.rs
@@ -1,6 +1,6 @@
 //! Ensure we trigger abi_unsupported_vector_types for target features that are usually enabled
 //! on a target, but disabled in this file via a `-C` flag.
-//@ compile-flags: --crate-type=rlib --target=i686-unknown-linux-gnu -C target-feature=-sse,-sse2
+//@ compile-flags: --crate-type=rlib --target=i586-unknown-linux-gnu -C target-feature=-sse,-sse2
 //@ build-pass
 //@ ignore-pass (test emits codegen-time warnings)
 //@ needs-llvm-components: x86
diff --git a/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs
new file mode 100644
index 00000000000..28d026c1a9a
--- /dev/null
+++ b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.rs
@@ -0,0 +1,12 @@
+//@ compile-flags: --target=i686-unknown-linux-gnu --crate-type=lib
+//@ needs-llvm-components: x86
+//@ compile-flags: -Ctarget-cpu=pentium
+// For now this is just a warning.
+//@ build-pass
+//@error-pattern: must be enabled
+
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
diff --git a/tests/ui/target-feature/target-cpu-lacks-required-target-feature.stderr b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.stderr
new file mode 100644
index 00000000000..7ec8b04cfce
--- /dev/null
+++ b/tests/ui/target-feature/target-cpu-lacks-required-target-feature.stderr
@@ -0,0 +1,7 @@
+warning: target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly
+   |
+   = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
+
+warning: 1 warning emitted
+