about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-04 19:44:14 +0000
committerbors <bors@rust-lang.org>2024-01-04 19:44:14 +0000
commit4c5ce1f0d5bf8b2ee35ff6917658ba56ef57643b (patch)
treed4ae642bdb3ae0af49c83ea1866217cc4c07581a /src
parent090d5eac722000906cc00d991f2bf052b0e388c3 (diff)
parent657937850b3fbc2668516a21c2437af45a16889d (diff)
downloadrust-4c5ce1f0d5bf8b2ee35ff6917658ba56ef57643b.tar.gz
rust-4c5ce1f0d5bf8b2ee35ff6917658ba56ef57643b.zip
Auto merge of #119578 - matthiaskrgr:rollup-42yizmx, r=matthiaskrgr
Rollup of 10 pull requests

Successful merges:

 - #117636 (add test for #117626)
 - #118704 (Promote `riscv32{im|imafc}` targets to tier 2)
 - #119184 (Switch from using `//~ERROR` annotations with `--error-format` to `error-pattern`)
 - #119325 (custom mir: make it clear what the return block is)
 - #119391 (Use Result::flatten in catch_with_exit_code)
 - #119431 (Support reg_addr register class in s390x inline assembly)
 - #119475 (Remove libtest's dylib)
 - #119532 (Make offset_of field parsing use metavariable which handles any spacing)
 - #119553 (stop feed vis when cant access for trait item)
 - #119574 (Miri subtree update)

r? `@ghost`
`@rustbot` modify labels: rollup
Diffstat (limited to 'src')
-rw-r--r--src/doc/rustc/src/platform-support.md4
-rw-r--r--src/doc/rustc/src/platform-support/riscv32imac-unknown-none-elf.md8
-rw-r--r--src/doc/unstable-book/src/language-features/asm-experimental-arch.md5
-rw-r--r--src/tools/compiletest/src/errors.rs2
-rw-r--r--src/tools/compiletest/src/runtest.rs26
-rw-r--r--src/tools/miri/src/helpers.rs53
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/operator.rs4
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs108
-rw-r--r--src/tools/miri/src/shims/intrinsics/mod.rs172
-rw-r--r--src/tools/miri/src/shims/intrinsics/simd.rs167
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs17
-rw-r--r--src/tools/miri/src/shims/unix/mem.rs22
-rw-r--r--src/tools/miri/test_dependencies/Cargo.lock159
-rw-r--r--src/tools/miri/test_dependencies/Cargo.toml4
-rw-r--r--src/tools/miri/tests/compiletest.rs2
-rw-r--r--src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.rs (renamed from src/tools/miri/tests/fail/concurrency/windows_join_detached.rs)8
-rw-r--r--src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.stderr (renamed from src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr)0
-rw-r--r--src/tools/miri/tests/fail-dep/concurrency/windows_join_main.rs (renamed from src/tools/miri/tests/fail/concurrency/windows_join_main.rs)11
-rw-r--r--src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr (renamed from src/tools/miri/tests/fail/concurrency/windows_join_main.stderr)4
-rw-r--r--src/tools/miri/tests/fail-dep/concurrency/windows_join_self.rs (renamed from src/tools/miri/tests/fail/concurrency/windows_join_self.rs)10
-rw-r--r--src/tools/miri/tests/fail-dep/concurrency/windows_join_self.stderr (renamed from src/tools/miri/tests/fail/concurrency/windows_join_self.stderr)2
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/fast_math_both.rs (renamed from src/tools/miri/tests/fail/fast_math_both.rs)0
-rw-r--r--src/tools/miri/tests/fail/intrinsics/fast_math_both.stderr (renamed from src/tools/miri/tests/fail/fast_math_both.stderr)0
-rw-r--r--src/tools/miri/tests/fail/intrinsics/fast_math_first.rs (renamed from src/tools/miri/tests/fail/fast_math_first.rs)0
-rw-r--r--src/tools/miri/tests/fail/intrinsics/fast_math_first.stderr (renamed from src/tools/miri/tests/fail/fast_math_first.stderr)0
-rw-r--r--src/tools/miri/tests/fail/intrinsics/fast_math_result.rs7
-rw-r--r--src/tools/miri/tests/fail/intrinsics/fast_math_result.stderr15
-rw-r--r--src/tools/miri/tests/fail/intrinsics/fast_math_second.rs (renamed from src/tools/miri/tests/fail/fast_math_second.rs)0
-rw-r--r--src/tools/miri/tests/fail/intrinsics/fast_math_second.stderr (renamed from src/tools/miri/tests/fail/fast_math_second.stderr)0
-rw-r--r--src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs2
-rw-r--r--src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr4
-rw-r--r--src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.rs (renamed from src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs)41
-rw-r--r--src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.stdout (renamed from src/tools/miri/tests/pass/concurrency/windows_condvar_shared.stdout)0
-rw-r--r--src/tools/miri/tests/pass-dep/concurrency/windows_detach_terminated.rs (renamed from src/tools/miri/tests/pass/concurrency/windows_detach_terminated.rs)6
-rw-r--r--src/tools/miri/tests/pass-dep/concurrency/windows_init_once.rs (renamed from src/tools/miri/tests/pass/concurrency/windows_init_once.rs)35
-rw-r--r--src/tools/miri/tests/pass-dep/concurrency/windows_init_once.stdout (renamed from src/tools/miri/tests/pass/concurrency/windows_init_once.stdout)0
-rw-r--r--src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs (renamed from src/tools/miri/tests/pass/concurrency/windows_join_multiple.rs)11
-rw-r--r--src/tools/miri/tests/pass-dep/shims/mmap.rs21
-rw-r--r--src/tools/miri/tests/pass-dep/tempfile.rs21
-rw-r--r--src/tools/miri/tests/pass/float_nan.rs172
-rw-r--r--src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs2
58 files changed, 822 insertions, 358 deletions
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 09070168b67..0d8213f048d 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -161,7 +161,9 @@ target | std | notes
 [`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs]
 [`riscv32imac-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAC ISA)
 [`riscv32i-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32I ISA)
+[`riscv32im-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * |  | Bare RISC-V (RV32IM ISA)
 [`riscv32imc-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMC ISA)
+[`riscv32imafc-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA)
 `riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA)
 `riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA)
 `sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4, glibc 2.23)
@@ -318,8 +320,6 @@ target | std | host | notes
 [`powerpc64-ibm-aix`](platform-support/aix.md) | ? |  | 64-bit AIX (7.2 and newer)
 `riscv32gc-unknown-linux-gnu` |   |   | RISC-V Linux (kernel 5.4, glibc 2.33)
 `riscv32gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches)
-[`riscv32imafc-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA)
-[`riscv32im-unknown-none-elf`](platform-support/riscv32imac-unknown-none-elf.md) | * |  | Bare RISC-V (RV32IM ISA)
 [`riscv32imac-unknown-xous-elf`](platform-support/riscv32imac-unknown-xous-elf.md) | ? |  | RISC-V Xous (RV32IMAC ISA)
 [`riscv32imc-esp-espidf`](platform-support/esp-idf.md) | ✓ |  | RISC-V ESP-IDF
 [`riscv32imac-esp-espidf`](platform-support/esp-idf.md) | ✓ |  | RISC-V ESP-IDF
diff --git a/src/doc/rustc/src/platform-support/riscv32imac-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv32imac-unknown-none-elf.md
index a069f3d3aa9..739b12bad8b 100644
--- a/src/doc/rustc/src/platform-support/riscv32imac-unknown-none-elf.md
+++ b/src/doc/rustc/src/platform-support/riscv32imac-unknown-none-elf.md
@@ -1,6 +1,6 @@
 # `riscv32{i,im,imc,imac,imafc}-unknown-none-elf`
 
-**Tier: 2/3**
+**Tier: 2**
 
 Bare-metal target for RISC-V CPUs with the RV32I, RV32IM, RV32IMC, RV32IMAFC and RV32IMAC ISAs.
 
@@ -24,11 +24,11 @@ This target is included in Rust and can be installed via `rustup`.
 
 ## Testing
 
-This is a cross-compiled no-std target, which must be run either in a simulator
+This is a cross-compiled `no-std` target, which must be run either in a simulator
 or by programming them onto suitable hardware. It is not possible to run the
-Rust testsuite on this target.
+Rust test-suite on this target.
 
 ## Cross-compilation toolchains and C code
 
 This target supports C code. If interlinking with C or C++, you may need to use
-riscv64-unknown-elf-gcc as a linker instead of rust-lld.
+`riscv64-unknown-elf-gcc` as a linker instead of `rust-lld`.
diff --git a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
index 968c9bb4ebb..59acbc73db4 100644
--- a/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
+++ b/src/doc/unstable-book/src/language-features/asm-experimental-arch.md
@@ -84,7 +84,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | M68k         | `reg_data`                      | None           | `i8`, `i16`, `i32`                      |
 | CSKY         | `reg`                           | None           | `i8`, `i16`, `i32`                      |
 | CSKY         | `freg`                          | None           | `f32`,                                  |
-| s390x        | `reg`                           | None           | `i8`, `i16`, `i32`, `i64`               |
+| s390x        | `reg`, `reg_addr`               | None           | `i8`, `i16`, `i32`, `i64`               |
 | s390x        | `freg`                          | None           | `f32`, `f64`                            |
 
 ## Register aliases
@@ -158,9 +158,10 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
 | NVPTX        | `reg64`        | None     | `rd0`          | None          |
 | Hexagon      | `reg`          | None     | `r0`           | None          |
 | PowerPC      | `reg`          | None     | `0`            | None          |
-| PowerPC      | `reg_nonzero`  | None     | `3`            | `b`           |
+| PowerPC      | `reg_nonzero`  | None     | `3`            | None          |
 | PowerPC      | `freg`         | None     | `0`            | None          |
 | s390x        | `reg`          | None     | `%r0`          | None          |
+| s390x        | `reg_addr`     | None     | `%r1`          | None          |
 | s390x        | `freg`         | None     | `%f0`          | None          |
 | CSKY         | `reg`          | None     | `r0`           | None          |
 | CSKY         | `freg`         | None     | `f0`           | None          |
diff --git a/src/tools/compiletest/src/errors.rs b/src/tools/compiletest/src/errors.rs
index c33e66e02ac..e0ec76aa027 100644
--- a/src/tools/compiletest/src/errors.rs
+++ b/src/tools/compiletest/src/errors.rs
@@ -11,7 +11,7 @@ use once_cell::sync::Lazy;
 use regex::Regex;
 use tracing::*;
 
-#[derive(Clone, Debug, PartialEq)]
+#[derive(Copy, Clone, Debug, PartialEq)]
 pub enum ErrorKind {
     Help,
     Error,
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index ca80328f3ac..1f5f77839de 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -3977,23 +3977,29 @@ impl<'test> TestCx<'test> {
             proc_res.status,
             self.props.error_patterns
         );
-        if !explicit && self.config.compare_mode.is_none() {
-            let check_patterns = should_run == WillExecute::No
-                && (!self.props.error_patterns.is_empty()
-                    || !self.props.regex_error_patterns.is_empty());
 
+        let check_patterns = should_run == WillExecute::No
+            && (!self.props.error_patterns.is_empty()
+                || !self.props.regex_error_patterns.is_empty());
+        if !explicit && self.config.compare_mode.is_none() {
             let check_annotations = !check_patterns || !expected_errors.is_empty();
 
-            if check_patterns {
-                // "// error-pattern" comments
-                let output_to_check = self.get_output(&proc_res);
-                self.check_all_error_patterns(&output_to_check, &proc_res, pm);
-            }
-
             if check_annotations {
                 // "//~ERROR comments"
                 self.check_expected_errors(expected_errors, &proc_res);
             }
+        } else if explicit && !expected_errors.is_empty() {
+            let msg = format!(
+                "line {}: cannot combine `--error-format` with {} annotations; use `error-pattern` instead",
+                expected_errors[0].line_num,
+                expected_errors[0].kind.unwrap_or(ErrorKind::Error),
+            );
+            self.fatal(&msg);
+        }
+        if check_patterns {
+            // "// error-pattern" comments
+            let output_to_check = self.get_output(&proc_res);
+            self.check_all_error_patterns(&output_to_check, &proc_res, pm);
         }
 
         if self.props.run_rustfix && self.config.compare_mode.is_none() {
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index d2fd51b099a..14ba69b898b 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -6,6 +6,7 @@ use std::time::Duration;
 use log::trace;
 
 use rustc_apfloat::ieee::{Double, Single};
+use rustc_apfloat::Float;
 use rustc_hir::def::{DefKind, Namespace};
 use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc_index::IndexVec;
@@ -117,6 +118,50 @@ fn try_resolve_did(tcx: TyCtxt<'_>, path: &[&str], namespace: Option<Namespace>)
     }
 }
 
+/// Convert a softfloat type to its corresponding hostfloat type.
+pub trait ToHost {
+    type HostFloat;
+    fn to_host(self) -> Self::HostFloat;
+}
+
+/// Convert a hostfloat type to its corresponding softfloat type.
+pub trait ToSoft {
+    type SoftFloat;
+    fn to_soft(self) -> Self::SoftFloat;
+}
+
+impl ToHost for rustc_apfloat::ieee::Double {
+    type HostFloat = f64;
+
+    fn to_host(self) -> Self::HostFloat {
+        f64::from_bits(self.to_bits().try_into().unwrap())
+    }
+}
+
+impl ToSoft for f64 {
+    type SoftFloat = rustc_apfloat::ieee::Double;
+
+    fn to_soft(self) -> Self::SoftFloat {
+        Float::from_bits(self.to_bits().into())
+    }
+}
+
+impl ToHost for rustc_apfloat::ieee::Single {
+    type HostFloat = f32;
+
+    fn to_host(self) -> Self::HostFloat {
+        f32::from_bits(self.to_bits().try_into().unwrap())
+    }
+}
+
+impl ToSoft for f32 {
+    type SoftFloat = rustc_apfloat::ieee::Single;
+
+    fn to_soft(self) -> Self::SoftFloat {
+        Float::from_bits(self.to_bits().into())
+    }
+}
+
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     /// Checks if the given crate/module exists.
@@ -1188,11 +1233,3 @@ pub(crate) fn simd_element_to_bool(elem: ImmTy<'_, Provenance>) -> InterpResult<
         _ => throw_ub_format!("each element of a SIMD mask must be all-0-bits or all-1-bits"),
     })
 }
-
-// This looks like something that would be nice to have in the standard library...
-pub(crate) fn round_to_next_multiple_of(x: u64, divisor: u64) -> u64 {
-    assert_ne!(divisor, 0);
-    // divisor is nonzero; multiplication cannot overflow since we just divided
-    #[allow(clippy::arithmetic_side_effects)]
-    return (x.checked_add(divisor - 1).unwrap() / divisor) * divisor;
-}
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 4e9febf0205..cacd02bbfae 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -11,6 +11,7 @@
 #![feature(round_ties_even)]
 #![feature(let_chains)]
 #![feature(lint_reasons)]
+#![feature(int_roundings)]
 // Configure clippy and other lints
 #![allow(
     clippy::collapsible_else_if,
diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs
index e5a437f95f0..14076444696 100644
--- a/src/tools/miri/src/operator.rs
+++ b/src/tools/miri/src/operator.rs
@@ -118,4 +118,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             nan
         }
     }
+
+    fn adjust_nan<F1: Float + FloatConvert<F2>, F2: Float>(&self, f: F2, inputs: &[F1]) -> F2 {
+        if f.is_nan() { self.generate_nan(inputs) } else { f }
+    }
 }
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 8ddfc05dd30..e7b2a6823ed 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -23,6 +23,7 @@ use rustc_target::{
 
 use super::backtrace::EvalContextExt as _;
 use crate::*;
+use helpers::{ToHost, ToSoft};
 
 /// Type of dynamic symbols (for `dlsym` et al)
 #[derive(Debug, Copy, Clone)]
@@ -886,23 +887,26 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             | "tgammaf"
             => {
                 let [f] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let f = this.read_scalar(f)?.to_f32()?;
                 // FIXME: Using host floats.
-                let f = f32::from_bits(this.read_scalar(f)?.to_u32()?);
+                let f_host = f.to_host();
                 let res = match link_name.as_str() {
-                    "cbrtf" => f.cbrt(),
-                    "coshf" => f.cosh(),
-                    "sinhf" => f.sinh(),
-                    "tanf" => f.tan(),
-                    "tanhf" => f.tanh(),
-                    "acosf" => f.acos(),
-                    "asinf" => f.asin(),
-                    "atanf" => f.atan(),
-                    "log1pf" => f.ln_1p(),
-                    "expm1f" => f.exp_m1(),
-                    "tgammaf" => f.gamma(),
+                    "cbrtf" => f_host.cbrt(),
+                    "coshf" => f_host.cosh(),
+                    "sinhf" => f_host.sinh(),
+                    "tanf" => f_host.tan(),
+                    "tanhf" => f_host.tanh(),
+                    "acosf" => f_host.acos(),
+                    "asinf" => f_host.asin(),
+                    "atanf" => f_host.atan(),
+                    "log1pf" => f_host.ln_1p(),
+                    "expm1f" => f_host.exp_m1(),
+                    "tgammaf" => f_host.gamma(),
                     _ => bug!(),
                 };
-                this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
+                let res = res.to_soft();
+                let res = this.adjust_nan(res, &[f]);
+                this.write_scalar(res, dest)?;
             }
             #[rustfmt::skip]
             | "_hypotf"
@@ -911,19 +915,20 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             | "fdimf"
             => {
                 let [f1, f2] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let f1 = this.read_scalar(f1)?.to_f32()?;
+                let f2 = this.read_scalar(f2)?.to_f32()?;
                 // underscore case for windows, here and below
                 // (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019)
                 // FIXME: Using host floats.
-                let f1 = f32::from_bits(this.read_scalar(f1)?.to_u32()?);
-                let f2 = f32::from_bits(this.read_scalar(f2)?.to_u32()?);
                 let res = match link_name.as_str() {
-                    "_hypotf" | "hypotf" => f1.hypot(f2),
-                    "atan2f" => f1.atan2(f2),
+                    "_hypotf" | "hypotf" => f1.to_host().hypot(f2.to_host()).to_soft(),
+                    "atan2f" => f1.to_host().atan2(f2.to_host()).to_soft(),
                     #[allow(deprecated)]
-                    "fdimf" => f1.abs_sub(f2),
+                    "fdimf" => f1.to_host().abs_sub(f2.to_host()).to_soft(),
                     _ => bug!(),
                 };
-                this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
+                let res = this.adjust_nan(res, &[f1, f2]);
+                this.write_scalar(res, dest)?;
             }
             #[rustfmt::skip]
             | "cbrt"
@@ -939,23 +944,26 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             | "tgamma"
             => {
                 let [f] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let f = this.read_scalar(f)?.to_f64()?;
                 // FIXME: Using host floats.
-                let f = f64::from_bits(this.read_scalar(f)?.to_u64()?);
+                let f_host = f.to_host();
                 let res = match link_name.as_str() {
-                    "cbrt" => f.cbrt(),
-                    "cosh" => f.cosh(),
-                    "sinh" => f.sinh(),
-                    "tan" => f.tan(),
-                    "tanh" => f.tanh(),
-                    "acos" => f.acos(),
-                    "asin" => f.asin(),
-                    "atan" => f.atan(),
-                    "log1p" => f.ln_1p(),
-                    "expm1" => f.exp_m1(),
-                    "tgamma" => f.gamma(),
+                    "cbrt" => f_host.cbrt(),
+                    "cosh" => f_host.cosh(),
+                    "sinh" => f_host.sinh(),
+                    "tan" => f_host.tan(),
+                    "tanh" => f_host.tanh(),
+                    "acos" => f_host.acos(),
+                    "asin" => f_host.asin(),
+                    "atan" => f_host.atan(),
+                    "log1p" => f_host.ln_1p(),
+                    "expm1" => f_host.exp_m1(),
+                    "tgamma" => f_host.gamma(),
                     _ => bug!(),
                 };
-                this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
+                let res = res.to_soft();
+                let res = this.adjust_nan(res, &[f]);
+                this.write_scalar(res, dest)?;
             }
             #[rustfmt::skip]
             | "_hypot"
@@ -964,17 +972,20 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             | "fdim"
             => {
                 let [f1, f2] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
+                let f1 = this.read_scalar(f1)?.to_f64()?;
+                let f2 = this.read_scalar(f2)?.to_f64()?;
+                // underscore case for windows, here and below
+                // (see https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/floating-point-primitives?view=vs-2019)
                 // FIXME: Using host floats.
-                let f1 = f64::from_bits(this.read_scalar(f1)?.to_u64()?);
-                let f2 = f64::from_bits(this.read_scalar(f2)?.to_u64()?);
                 let res = match link_name.as_str() {
-                    "_hypot" | "hypot" => f1.hypot(f2),
-                    "atan2" => f1.atan2(f2),
+                    "_hypot" | "hypot" => f1.to_host().hypot(f2.to_host()).to_soft(),
+                    "atan2" => f1.to_host().atan2(f2.to_host()).to_soft(),
                     #[allow(deprecated)]
-                    "fdim" => f1.abs_sub(f2),
+                    "fdim" => f1.to_host().abs_sub(f2.to_host()).to_soft(),
                     _ => bug!(),
                 };
-                this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
+                let res = this.adjust_nan(res, &[f1, f2]);
+                this.write_scalar(res, dest)?;
             }
             #[rustfmt::skip]
             | "_ldexp"
@@ -987,27 +998,30 @@ trait EvalContextExtPriv<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let exp = this.read_scalar(exp)?.to_i32()?;
 
                 let res = x.scalbn(exp);
-                this.write_scalar(Scalar::from_f64(res), dest)?;
+                let res = this.adjust_nan(res, &[x]);
+                this.write_scalar(res, dest)?;
             }
             "lgammaf_r" => {
                 let [x, signp] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                // FIXME: Using host floats.
-                let x = f32::from_bits(this.read_scalar(x)?.to_u32()?);
+                let x = this.read_scalar(x)?.to_f32()?;
                 let signp = this.deref_pointer(signp)?;
 
-                let (res, sign) = x.ln_gamma();
+                // FIXME: Using host floats.
+                let (res, sign) = x.to_host().ln_gamma();
                 this.write_int(sign, &signp)?;
-                this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
+                let res = this.adjust_nan(res.to_soft(), &[x]);
+                this.write_scalar(res, dest)?;
             }
             "lgamma_r" => {
                 let [x, signp] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
-                // FIXME: Using host floats.
-                let x = f64::from_bits(this.read_scalar(x)?.to_u64()?);
+                let x = this.read_scalar(x)?.to_f64()?;
                 let signp = this.deref_pointer(signp)?;
 
-                let (res, sign) = x.ln_gamma();
+                // FIXME: Using host floats.
+                let (res, sign) = x.to_host().ln_gamma();
                 this.write_int(sign, &signp)?;
-                this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
+                let res = this.adjust_nan(res.to_soft(), &[x]);
+                this.write_scalar(res, dest)?;
             }
 
             // LLVM intrinsics
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs
index 66918db995d..cc81ef6e6c9 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/shims/intrinsics/mod.rs
@@ -15,7 +15,7 @@ use rustc_target::abi::Size;
 
 use crate::*;
 use atomic::EvalContextExt as _;
-use helpers::check_arg_count;
+use helpers::{check_arg_count, ToHost, ToSoft};
 use simd::EvalContextExt as _;
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
@@ -146,12 +146,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let [f] = check_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f32()?;
                 // Can be implemented in soft-floats.
+                // This is a "bitwise" operation, so there's no NaN non-determinism.
                 this.write_scalar(Scalar::from_f32(f.abs()), dest)?;
             }
             "fabsf64" => {
                 let [f] = check_arg_count(args)?;
                 let f = this.read_scalar(f)?.to_f64()?;
                 // Can be implemented in soft-floats.
+                // This is a "bitwise" operation, so there's no NaN non-determinism.
                 this.write_scalar(Scalar::from_f64(f.abs()), dest)?;
             }
             #[rustfmt::skip]
@@ -170,25 +172,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             | "rintf32"
             => {
                 let [f] = check_arg_count(args)?;
+                let f = this.read_scalar(f)?.to_f32()?;
                 // FIXME: Using host floats.
-                let f = f32::from_bits(this.read_scalar(f)?.to_u32()?);
-                let f = match intrinsic_name {
-                    "sinf32" => f.sin(),
-                    "cosf32" => f.cos(),
-                    "sqrtf32" => f.sqrt(),
-                    "expf32" => f.exp(),
-                    "exp2f32" => f.exp2(),
-                    "logf32" => f.ln(),
-                    "log10f32" => f.log10(),
-                    "log2f32" => f.log2(),
-                    "floorf32" => f.floor(),
-                    "ceilf32" => f.ceil(),
-                    "truncf32" => f.trunc(),
-                    "roundf32" => f.round(),
-                    "rintf32" => f.round_ties_even(),
+                let f_host = f.to_host();
+                let res = match intrinsic_name {
+                    "sinf32" => f_host.sin(),
+                    "cosf32" => f_host.cos(),
+                    "sqrtf32" => f_host.sqrt(),
+                    "expf32" => f_host.exp(),
+                    "exp2f32" => f_host.exp2(),
+                    "logf32" => f_host.ln(),
+                    "log10f32" => f_host.log10(),
+                    "log2f32" => f_host.log2(),
+                    "floorf32" => f_host.floor(),
+                    "ceilf32" => f_host.ceil(),
+                    "truncf32" => f_host.trunc(),
+                    "roundf32" => f_host.round(),
+                    "rintf32" => f_host.round_ties_even(),
                     _ => bug!(),
                 };
-                this.write_scalar(Scalar::from_u32(f.to_bits()), dest)?;
+                let res = res.to_soft();
+                let res = this.adjust_nan(res, &[f]);
+                this.write_scalar(res, dest)?;
             }
 
             #[rustfmt::skip]
@@ -207,25 +212,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             | "rintf64"
             => {
                 let [f] = check_arg_count(args)?;
+                let f = this.read_scalar(f)?.to_f64()?;
                 // FIXME: Using host floats.
-                let f = f64::from_bits(this.read_scalar(f)?.to_u64()?);
-                let f = match intrinsic_name {
-                    "sinf64" => f.sin(),
-                    "cosf64" => f.cos(),
-                    "sqrtf64" => f.sqrt(),
-                    "expf64" => f.exp(),
-                    "exp2f64" => f.exp2(),
-                    "logf64" => f.ln(),
-                    "log10f64" => f.log10(),
-                    "log2f64" => f.log2(),
-                    "floorf64" => f.floor(),
-                    "ceilf64" => f.ceil(),
-                    "truncf64" => f.trunc(),
-                    "roundf64" => f.round(),
-                    "rintf64" => f.round_ties_even(),
+                let f_host = f.to_host();
+                let res = match intrinsic_name {
+                    "sinf64" => f_host.sin(),
+                    "cosf64" => f_host.cos(),
+                    "sqrtf64" => f_host.sqrt(),
+                    "expf64" => f_host.exp(),
+                    "exp2f64" => f_host.exp2(),
+                    "logf64" => f_host.ln(),
+                    "log10f64" => f_host.log10(),
+                    "log2f64" => f_host.log2(),
+                    "floorf64" => f_host.floor(),
+                    "ceilf64" => f_host.ceil(),
+                    "truncf64" => f_host.trunc(),
+                    "roundf64" => f_host.round(),
+                    "rintf64" => f_host.round_ties_even(),
                     _ => bug!(),
                 };
-                this.write_scalar(Scalar::from_u64(f.to_bits()), dest)?;
+                let res = res.to_soft();
+                let res = this.adjust_nan(res, &[f]);
+                this.write_scalar(res, dest)?;
             }
 
             #[rustfmt::skip]
@@ -268,7 +276,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     ),
                     _ => {}
                 }
-                this.binop_ignore_overflow(op, &a, &b, dest)?;
+                let res = this.wrapping_binary_op(op, &a, &b)?;
+                if !float_finite(&res)? {
+                    throw_ub_format!("`{intrinsic_name}` intrinsic produced non-finite value as result");
+                }
+                // This cannot be a NaN so we also don't have to apply any non-determinism.
+                // (Also, `wrapping_binary_op` already called `generate_nan` if needed.)
+                this.write_immediate(*res, dest)?;
             }
 
             #[rustfmt::skip]
@@ -280,9 +294,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let a = this.read_scalar(a)?.to_f32()?;
                 let b = this.read_scalar(b)?.to_f32()?;
                 let res = match intrinsic_name {
-                    "minnumf32" => a.min(b),
-                    "maxnumf32" => a.max(b),
-                    "copysignf32" => a.copy_sign(b),
+                    "minnumf32" => this.adjust_nan(a.min(b), &[a, b]),
+                    "maxnumf32" => this.adjust_nan(a.max(b), &[a, b]),
+                    "copysignf32" => a.copy_sign(b), // bitwise, no NaN adjustments
                     _ => bug!(),
                 };
                 this.write_scalar(Scalar::from_f32(res), dest)?;
@@ -297,68 +311,74 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let a = this.read_scalar(a)?.to_f64()?;
                 let b = this.read_scalar(b)?.to_f64()?;
                 let res = match intrinsic_name {
-                    "minnumf64" => a.min(b),
-                    "maxnumf64" => a.max(b),
-                    "copysignf64" => a.copy_sign(b),
+                    "minnumf64" => this.adjust_nan(a.min(b), &[a, b]),
+                    "maxnumf64" => this.adjust_nan(a.max(b), &[a, b]),
+                    "copysignf64" => a.copy_sign(b), // bitwise, no NaN adjustments
                     _ => bug!(),
                 };
                 this.write_scalar(Scalar::from_f64(res), dest)?;
             }
 
-            "powf32" => {
-                let [f, f2] = check_arg_count(args)?;
-                // FIXME: Using host floats.
-                let f = f32::from_bits(this.read_scalar(f)?.to_u32()?);
-                let f2 = f32::from_bits(this.read_scalar(f2)?.to_u32()?);
-                let res = f.powf(f2);
-                this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
-            }
-
-            "powf64" => {
-                let [f, f2] = check_arg_count(args)?;
-                // FIXME: Using host floats.
-                let f = f64::from_bits(this.read_scalar(f)?.to_u64()?);
-                let f2 = f64::from_bits(this.read_scalar(f2)?.to_u64()?);
-                let res = f.powf(f2);
-                this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
-            }
-
             "fmaf32" => {
                 let [a, b, c] = check_arg_count(args)?;
+                let a = this.read_scalar(a)?.to_f32()?;
+                let b = this.read_scalar(b)?.to_f32()?;
+                let c = this.read_scalar(c)?.to_f32()?;
                 // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
-                let a = f32::from_bits(this.read_scalar(a)?.to_u32()?);
-                let b = f32::from_bits(this.read_scalar(b)?.to_u32()?);
-                let c = f32::from_bits(this.read_scalar(c)?.to_u32()?);
-                let res = a.mul_add(b, c);
-                this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
+                let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
+                let res = this.adjust_nan(res, &[a, b, c]);
+                this.write_scalar(res, dest)?;
             }
 
             "fmaf64" => {
                 let [a, b, c] = check_arg_count(args)?;
+                let a = this.read_scalar(a)?.to_f64()?;
+                let b = this.read_scalar(b)?.to_f64()?;
+                let c = this.read_scalar(c)?.to_f64()?;
                 // FIXME: Using host floats, to work around https://github.com/rust-lang/rustc_apfloat/issues/11
-                let a = f64::from_bits(this.read_scalar(a)?.to_u64()?);
-                let b = f64::from_bits(this.read_scalar(b)?.to_u64()?);
-                let c = f64::from_bits(this.read_scalar(c)?.to_u64()?);
-                let res = a.mul_add(b, c);
-                this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
+                let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
+                let res = this.adjust_nan(res, &[a, b, c]);
+                this.write_scalar(res, dest)?;
+            }
+
+            "powf32" => {
+                let [f1, f2] = check_arg_count(args)?;
+                let f1 = this.read_scalar(f1)?.to_f32()?;
+                let f2 = this.read_scalar(f2)?.to_f32()?;
+                // FIXME: Using host floats.
+                let res = f1.to_host().powf(f2.to_host()).to_soft();
+                let res = this.adjust_nan(res, &[f1, f2]);
+                this.write_scalar(res, dest)?;
+            }
+
+            "powf64" => {
+                let [f1, f2] = check_arg_count(args)?;
+                let f1 = this.read_scalar(f1)?.to_f64()?;
+                let f2 = this.read_scalar(f2)?.to_f64()?;
+                // FIXME: Using host floats.
+                let res = f1.to_host().powf(f2.to_host()).to_soft();
+                let res = this.adjust_nan(res, &[f1, f2]);
+                this.write_scalar(res, dest)?;
             }
 
             "powif32" => {
                 let [f, i] = check_arg_count(args)?;
-                // FIXME: Using host floats.
-                let f = f32::from_bits(this.read_scalar(f)?.to_u32()?);
+                let f = this.read_scalar(f)?.to_f32()?;
                 let i = this.read_scalar(i)?.to_i32()?;
-                let res = f.powi(i);
-                this.write_scalar(Scalar::from_u32(res.to_bits()), dest)?;
+                // FIXME: Using host floats.
+                let res = f.to_host().powi(i).to_soft();
+                let res = this.adjust_nan(res, &[f]);
+                this.write_scalar(res, dest)?;
             }
 
             "powif64" => {
                 let [f, i] = check_arg_count(args)?;
-                // FIXME: Using host floats.
-                let f = f64::from_bits(this.read_scalar(f)?.to_u64()?);
+                let f = this.read_scalar(f)?.to_f64()?;
                 let i = this.read_scalar(i)?.to_i32()?;
-                let res = f.powi(i);
-                this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
+                // FIXME: Using host floats.
+                let res = f.to_host().powi(i).to_soft();
+                let res = this.adjust_nan(res, &[f]);
+                this.write_scalar(res, dest)?;
             }
 
             "float_to_int_unchecked" => {
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index 2c8493d8aad..ea2d104694a 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -4,11 +4,15 @@ use rustc_middle::{mir, ty, ty::FloatTy};
 use rustc_span::{sym, Symbol};
 use rustc_target::abi::{Endian, HasDataLayout};
 
-use crate::helpers::{
-    bool_to_simd_element, check_arg_count, round_to_next_multiple_of, simd_element_to_bool,
-};
+use crate::helpers::{bool_to_simd_element, check_arg_count, simd_element_to_bool, ToHost, ToSoft};
 use crate::*;
 
+#[derive(Copy, Clone)]
+pub(crate) enum MinMax {
+    Min,
+    Max,
+}
+
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
 pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     /// Calls the simd intrinsic `intrinsic`; the `simd_` prefix has already been removed.
@@ -67,13 +71,17 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     let op = this.read_immediate(&this.project_index(&op, i)?)?;
                     let dest = this.project_index(&dest, i)?;
                     let val = match which {
-                        Op::MirOp(mir_op) => this.wrapping_unary_op(mir_op, &op)?.to_scalar(),
+                        Op::MirOp(mir_op) => {
+                            // This already does NaN adjustments
+                            this.wrapping_unary_op(mir_op, &op)?.to_scalar()
+                        }
                         Op::Abs => {
                             // Works for f32 and f64.
                             let ty::Float(float_ty) = op.layout.ty.kind() else {
                                 span_bug!(this.cur_span(), "{} operand is not a float", intrinsic_name)
                             };
                             let op = op.to_scalar();
+                            // "Bitwise" operation, no NaN adjustments
                             match float_ty {
                                 FloatTy::F32 => Scalar::from_f32(op.to_f32()?.abs()),
                                 FloatTy::F64 => Scalar::from_f64(op.to_f64()?.abs()),
@@ -86,14 +94,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                             // FIXME using host floats
                             match float_ty {
                                 FloatTy::F32 => {
-                                    let f = f32::from_bits(op.to_scalar().to_u32()?);
-                                    let res = f.sqrt();
-                                    Scalar::from_u32(res.to_bits())
+                                    let f = op.to_scalar().to_f32()?;
+                                    let res = f.to_host().sqrt().to_soft();
+                                    let res = this.adjust_nan(res, &[f]);
+                                    Scalar::from(res)
                                 }
                                 FloatTy::F64 => {
-                                    let f = f64::from_bits(op.to_scalar().to_u64()?);
-                                    let res = f.sqrt();
-                                    Scalar::from_u64(res.to_bits())
+                                    let f = op.to_scalar().to_f64()?;
+                                    let res = f.to_host().sqrt().to_soft();
+                                    let res = this.adjust_nan(res, &[f]);
+                                    Scalar::from(res)
                                 }
                             }
                         }
@@ -105,11 +115,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                                 FloatTy::F32 => {
                                     let f = op.to_scalar().to_f32()?;
                                     let res = f.round_to_integral(rounding).value;
+                                    let res = this.adjust_nan(res, &[f]);
                                     Scalar::from_f32(res)
                                 }
                                 FloatTy::F64 => {
                                     let f = op.to_scalar().to_f64()?;
                                     let res = f.round_to_integral(rounding).value;
+                                    let res = this.adjust_nan(res, &[f]);
                                     Scalar::from_f64(res)
                                 }
                             }
@@ -157,8 +169,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 enum Op {
                     MirOp(BinOp),
                     SaturatingOp(BinOp),
-                    FMax,
-                    FMin,
+                    FMinMax(MinMax),
                     WrappingOffset,
                 }
                 let which = match intrinsic_name {
@@ -178,8 +189,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     "le" => Op::MirOp(BinOp::Le),
                     "gt" => Op::MirOp(BinOp::Gt),
                     "ge" => Op::MirOp(BinOp::Ge),
-                    "fmax" => Op::FMax,
-                    "fmin" => Op::FMin,
+                    "fmax" => Op::FMinMax(MinMax::Max),
+                    "fmin" => Op::FMinMax(MinMax::Min),
                     "saturating_add" => Op::SaturatingOp(BinOp::Add),
                     "saturating_sub" => Op::SaturatingOp(BinOp::Sub),
                     "arith_offset" => Op::WrappingOffset,
@@ -192,6 +203,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     let dest = this.project_index(&dest, i)?;
                     let val = match which {
                         Op::MirOp(mir_op) => {
+                            // This does NaN adjustments.
                             let (val, overflowed) = this.overflowing_binary_op(mir_op, &left, &right)?;
                             if matches!(mir_op, BinOp::Shl | BinOp::Shr) {
                                 // Shifts have extra UB as SIMD operations that the MIR binop does not have.
@@ -225,11 +237,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                             let offset_ptr = ptr.wrapping_signed_offset(offset_bytes, this);
                             Scalar::from_maybe_pointer(offset_ptr, this)
                         }
-                        Op::FMax => {
-                            fmax_op(&left, &right)?
-                        }
-                        Op::FMin => {
-                            fmin_op(&left, &right)?
+                        Op::FMinMax(op) => {
+                            this.fminmax_op(op, &left, &right)?
                         }
                     };
                     this.write_scalar(val, &dest)?;
@@ -259,18 +268,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     };
                     let val = match float_ty {
                         FloatTy::F32 => {
-                            let a = f32::from_bits(a.to_u32()?);
-                            let b = f32::from_bits(b.to_u32()?);
-                            let c = f32::from_bits(c.to_u32()?);
-                            let res = a.mul_add(b, c);
-                            Scalar::from_u32(res.to_bits())
+                            let a = a.to_f32()?;
+                            let b = b.to_f32()?;
+                            let c = c.to_f32()?;
+                            let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
+                            let res = this.adjust_nan(res, &[a, b, c]);
+                            Scalar::from(res)
                         }
                         FloatTy::F64 => {
-                            let a = f64::from_bits(a.to_u64()?);
-                            let b = f64::from_bits(b.to_u64()?);
-                            let c = f64::from_bits(c.to_u64()?);
-                            let res = a.mul_add(b, c);
-                            Scalar::from_u64(res.to_bits())
+                            let a = a.to_f64()?;
+                            let b = b.to_f64()?;
+                            let c = c.to_f64()?;
+                            let res = a.to_host().mul_add(b.to_host(), c.to_host()).to_soft();
+                            let res = this.adjust_nan(res, &[a, b, c]);
+                            Scalar::from(res)
                         }
                     };
                     this.write_scalar(val, &dest)?;
@@ -295,8 +306,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 enum Op {
                     MirOp(BinOp),
                     MirOpBool(BinOp),
-                    Max,
-                    Min,
+                    MinMax(MinMax),
                 }
                 let which = match intrinsic_name {
                     "reduce_and" => Op::MirOp(BinOp::BitAnd),
@@ -304,8 +314,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     "reduce_xor" => Op::MirOp(BinOp::BitXor),
                     "reduce_any" => Op::MirOpBool(BinOp::BitOr),
                     "reduce_all" => Op::MirOpBool(BinOp::BitAnd),
-                    "reduce_max" => Op::Max,
-                    "reduce_min" => Op::Min,
+                    "reduce_max" => Op::MinMax(MinMax::Max),
+                    "reduce_min" => Op::MinMax(MinMax::Min),
                     _ => unreachable!(),
                 };
 
@@ -325,24 +335,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                             let op = imm_from_bool(simd_element_to_bool(op)?);
                             this.wrapping_binary_op(mir_op, &res, &op)?
                         }
-                        Op::Max => {
-                            if matches!(res.layout.ty.kind(), ty::Float(_)) {
-                                ImmTy::from_scalar(fmax_op(&res, &op)?, res.layout)
-                            } else {
-                                // Just boring integers, so NaNs to worry about
-                                if this.wrapping_binary_op(BinOp::Ge, &res, &op)?.to_scalar().to_bool()? {
-                                    res
-                                } else {
-                                    op
-                                }
-                            }
-                        }
-                        Op::Min => {
+                        Op::MinMax(mmop) => {
                             if matches!(res.layout.ty.kind(), ty::Float(_)) {
-                                ImmTy::from_scalar(fmin_op(&res, &op)?, res.layout)
+                                ImmTy::from_scalar(this.fminmax_op(mmop, &res, &op)?, res.layout)
                             } else {
                                 // Just boring integers, so NaNs to worry about
-                                if this.wrapping_binary_op(BinOp::Le, &res, &op)?.to_scalar().to_bool()? {
+                                let mirop = match mmop {
+                                    MinMax::Min => BinOp::Le,
+                                    MinMax::Max => BinOp::Ge,
+                                };
+                                if this.wrapping_binary_op(mirop, &res, &op)?.to_scalar().to_bool()? {
                                     res
                                 } else {
                                     op
@@ -402,7 +404,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let (yes, yes_len) = this.operand_to_simd(yes)?;
                 let (no, no_len) = this.operand_to_simd(no)?;
                 let (dest, dest_len) = this.place_to_simd(dest)?;
-                let bitmask_len = round_to_next_multiple_of(dest_len, 8);
+                let bitmask_len = dest_len.next_multiple_of(8);
 
                 // The mask must be an integer or an array.
                 assert!(
@@ -448,7 +450,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "bitmask" => {
                 let [op] = check_arg_count(args)?;
                 let (op, op_len) = this.operand_to_simd(op)?;
-                let bitmask_len = round_to_next_multiple_of(op_len, 8);
+                let bitmask_len = op_len.next_multiple_of(8);
 
                 // Returns either an unsigned integer or array of `u8`.
                 assert!(
@@ -709,6 +711,43 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
         Ok(())
     }
+
+    fn fminmax_op(
+        &self,
+        op: MinMax,
+        left: &ImmTy<'tcx, Provenance>,
+        right: &ImmTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx, Scalar<Provenance>> {
+        let this = self.eval_context_ref();
+        assert_eq!(left.layout.ty, right.layout.ty);
+        let ty::Float(float_ty) = left.layout.ty.kind() else {
+            bug!("fmax operand is not a float")
+        };
+        let left = left.to_scalar();
+        let right = right.to_scalar();
+        Ok(match float_ty {
+            FloatTy::F32 => {
+                let left = left.to_f32()?;
+                let right = right.to_f32()?;
+                let res = match op {
+                    MinMax::Min => left.min(right),
+                    MinMax::Max => left.max(right),
+                };
+                let res = this.adjust_nan(res, &[left, right]);
+                Scalar::from_f32(res)
+            }
+            FloatTy::F64 => {
+                let left = left.to_f64()?;
+                let right = right.to_f64()?;
+                let res = match op {
+                    MinMax::Min => left.min(right),
+                    MinMax::Max => left.max(right),
+                };
+                let res = this.adjust_nan(res, &[left, right]);
+                Scalar::from_f64(res)
+            }
+        })
+    }
 }
 
 fn simd_bitmask_index(idx: u32, vec_len: u32, endianness: Endian) -> u32 {
@@ -719,31 +758,3 @@ fn simd_bitmask_index(idx: u32, vec_len: u32, endianness: Endian) -> u32 {
         Endian::Big => vec_len - 1 - idx, // reverse order of bits
     }
 }
-
-fn fmax_op<'tcx>(
-    left: &ImmTy<'tcx, Provenance>,
-    right: &ImmTy<'tcx, Provenance>,
-) -> InterpResult<'tcx, Scalar<Provenance>> {
-    assert_eq!(left.layout.ty, right.layout.ty);
-    let ty::Float(float_ty) = left.layout.ty.kind() else { bug!("fmax operand is not a float") };
-    let left = left.to_scalar();
-    let right = right.to_scalar();
-    Ok(match float_ty {
-        FloatTy::F32 => Scalar::from_f32(left.to_f32()?.max(right.to_f32()?)),
-        FloatTy::F64 => Scalar::from_f64(left.to_f64()?.max(right.to_f64()?)),
-    })
-}
-
-fn fmin_op<'tcx>(
-    left: &ImmTy<'tcx, Provenance>,
-    right: &ImmTy<'tcx, Provenance>,
-) -> InterpResult<'tcx, Scalar<Provenance>> {
-    assert_eq!(left.layout.ty, right.layout.ty);
-    let ty::Float(float_ty) = left.layout.ty.kind() else { bug!("fmin operand is not a float") };
-    let left = left.to_scalar();
-    let right = right.to_scalar();
-    Ok(match float_ty {
-        FloatTy::F32 => Scalar::from_f32(left.to_f32()?.min(right.to_f32()?)),
-        FloatTy::F64 => Scalar::from_f64(left.to_f64()?.min(right.to_f64()?)),
-    })
-}
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index 1402f07dd38..99d8a3a2c91 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -559,8 +559,21 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 );
             };
 
-            if mode != 0o666 {
-                throw_unsup_format!("non-default mode 0o{:o} is not supported", mode);
+            #[cfg(unix)]
+            {
+                // Support all modes on UNIX host
+                use std::os::unix::fs::OpenOptionsExt;
+                options.mode(mode);
+            }
+            #[cfg(not(unix))]
+            {
+                // Only support default mode for non-UNIX (i.e. Windows) host
+                if mode != 0o666 {
+                    throw_unsup_format!(
+                        "non-default mode 0o{:o} is not supported on non-Unix hosts",
+                        mode
+                    );
+                }
             }
 
             mirror |= o_creat;
diff --git a/src/tools/miri/src/shims/unix/mem.rs b/src/tools/miri/src/shims/unix/mem.rs
index 5aa514715bc..d7dc17fa89f 100644
--- a/src/tools/miri/src/shims/unix/mem.rs
+++ b/src/tools/miri/src/shims/unix/mem.rs
@@ -14,7 +14,7 @@
 //! munmap shim which would partily unmap a region of address space previously mapped by mmap will
 //! report UB.
 
-use crate::{helpers::round_to_next_multiple_of, *};
+use crate::*;
 use rustc_target::abi::Size;
 
 impl<'mir, 'tcx: 'mir> EvalContextExt<'mir, 'tcx> for crate::MiriInterpCx<'mir, 'tcx> {}
@@ -96,7 +96,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
 
         let align = this.machine.page_align();
-        let map_length = round_to_next_multiple_of(length, this.machine.page_size);
+        let Some(map_length) = length.checked_next_multiple_of(this.machine.page_size) else {
+            this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
+            return Ok(this.eval_libc("MAP_FAILED"));
+        };
+        if map_length > this.target_usize_max() {
+            this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
+            return Ok(this.eval_libc("MAP_FAILED"));
+        }
 
         let ptr =
             this.allocate_ptr(Size::from_bytes(map_length), align, MiriMemoryKind::Mmap.into())?;
@@ -129,7 +136,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             return Ok(Scalar::from_i32(-1));
         }
 
-        let length = Size::from_bytes(round_to_next_multiple_of(length, this.machine.page_size));
+        let Some(length) = length.checked_next_multiple_of(this.machine.page_size) else {
+            this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
+            return Ok(Scalar::from_i32(-1));
+        };
+        if length > this.target_usize_max() {
+            this.set_last_error(Scalar::from_i32(this.eval_libc_i32("EINVAL")))?;
+            return Ok(this.eval_libc("MAP_FAILED"));
+        }
+
+        let length = Size::from_bytes(length);
         this.deallocate_ptr(
             addr,
             Some((length, this.machine.page_align())),
diff --git a/src/tools/miri/test_dependencies/Cargo.lock b/src/tools/miri/test_dependencies/Cargo.lock
index 8d18d8535d8..aa3b25e338a 100644
--- a/src/tools/miri/test_dependencies/Cargo.lock
+++ b/src/tools/miri/test_dependencies/Cargo.lock
@@ -45,6 +45,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
+name = "bitflags"
+version = "2.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+
+[[package]]
 name = "bumpalo"
 version = "3.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -72,6 +78,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
+name = "errno"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+dependencies = [
+ "libc",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
+
+[[package]]
 name = "getrandom"
 version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -123,6 +145,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
 
 [[package]]
+name = "linux-raw-sys"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
+
+[[package]]
 name = "lock_api"
 version = "0.4.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -161,7 +189,7 @@ checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
 dependencies = [
  "libc",
  "wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -174,7 +202,9 @@ dependencies = [
  "num_cpus",
  "page_size",
  "rand",
+ "tempfile",
  "tokio",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -230,9 +260,9 @@ checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall",
+ "redox_syscall 0.3.5",
  "smallvec",
- "windows-targets",
+ "windows-targets 0.48.5",
 ]
 
 [[package]]
@@ -301,7 +331,16 @@ version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
+dependencies = [
+ "bitflags 1.3.2",
 ]
 
 [[package]]
@@ -311,6 +350,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
 
 [[package]]
+name = "rustix"
+version = "0.38.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
+dependencies = [
+ "bitflags 2.4.1",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
 name = "scopeguard"
 version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -338,7 +390,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e"
 dependencies = [
  "libc",
- "windows-sys",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -353,6 +405,19 @@ dependencies = [
 ]
 
 [[package]]
+name = "tempfile"
+version = "3.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "redox_syscall 0.4.1",
+ "rustix",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
 name = "tokio"
 version = "1.32.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -368,7 +433,7 @@ dependencies = [
  "signal-hook-registry",
  "socket2",
  "tokio-macros",
- "windows-sys",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -482,7 +547,16 @@ version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
 dependencies = [
- "windows-targets",
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.0",
 ]
 
 [[package]]
@@ -491,13 +565,28 @@ version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
 dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.0",
+ "windows_aarch64_msvc 0.52.0",
+ "windows_i686_gnu 0.52.0",
+ "windows_i686_msvc 0.52.0",
+ "windows_x86_64_gnu 0.52.0",
+ "windows_x86_64_gnullvm 0.52.0",
+ "windows_x86_64_msvc 0.52.0",
 ]
 
 [[package]]
@@ -507,37 +596,79 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
 [[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
+
+[[package]]
 name = "windows_aarch64_msvc"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
+
+[[package]]
 name = "windows_i686_gnu"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
+name = "windows_i686_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
+
+[[package]]
 name = "windows_i686_msvc"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
+name = "windows_i686_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
+
+[[package]]
 name = "windows_x86_64_gnu"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
+
+[[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
+
+[[package]]
 name = "windows_x86_64_msvc"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
diff --git a/src/tools/miri/test_dependencies/Cargo.toml b/src/tools/miri/test_dependencies/Cargo.toml
index d54560608dc..9f28e4d169f 100644
--- a/src/tools/miri/test_dependencies/Cargo.toml
+++ b/src/tools/miri/test_dependencies/Cargo.toml
@@ -11,6 +11,7 @@ edition = "2021"
 # all dependencies (and their transitive ones) listed here can be used in `tests/`.
 libc = "0.2"
 num_cpus = "1.10.1"
+tempfile = "3"
 
 getrandom_01 = { package = "getrandom", version = "0.1" }
 getrandom_02 = { package = "getrandom", version = "0.2", features = ["js"] }
@@ -20,4 +21,7 @@ rand = { version = "0.8", features = ["small_rng"] }
 page_size = "0.6"
 tokio = { version = "1.24", features = ["full"] }
 
+[target.'cfg(windows)'.dependencies]
+windows-sys = { version = "0.52", features = [ "Win32_Foundation", "Win32_System_Threading" ] }
+
 [workspace]
diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs
index 3394c4a49f8..074808b1122 100644
--- a/src/tools/miri/tests/compiletest.rs
+++ b/src/tools/miri/tests/compiletest.rs
@@ -111,6 +111,8 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
             "run".into(), // There is no `cargo miri build` so we just use `cargo miri run`.
         ]);
         config.dependency_builder.args = builder_args.into_iter().map(Into::into).collect();
+        // Reset `RUSTFLAGS` to work around <https://github.com/rust-lang/rust/pull/119574#issuecomment-1876878344>.
+        config.dependency_builder.envs.push(("RUSTFLAGS".into(), None));
     }
     config
 }
diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_detached.rs b/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.rs
index b68a07797f8..0e9eb24459c 100644
--- a/src/tools/miri/tests/fail/concurrency/windows_join_detached.rs
+++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.rs
@@ -3,18 +3,16 @@
 
 // Joining a detached thread is undefined behavior.
 
-use std::os::windows::io::{AsRawHandle, RawHandle};
+use std::os::windows::io::AsRawHandle;
 use std::thread;
 
-extern "system" {
-    fn CloseHandle(handle: RawHandle) -> u32;
-}
+use windows_sys::Win32::Foundation::{CloseHandle, HANDLE};
 
 fn main() {
     let thread = thread::spawn(|| ());
 
     unsafe {
-        assert_ne!(CloseHandle(thread.as_raw_handle()), 0);
+        assert_ne!(CloseHandle(thread.as_raw_handle() as HANDLE), 0);
     }
 
     thread.join().unwrap();
diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr b/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.stderr
index 651c2eba0d9..651c2eba0d9 100644
--- a/src/tools/miri/tests/fail/concurrency/windows_join_detached.stderr
+++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_detached.stderr
diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_main.rs b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.rs
index cde6d19ef25..910e06222ee 100644
--- a/src/tools/miri/tests/fail/concurrency/windows_join_main.rs
+++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.rs
@@ -6,21 +6,18 @@
 
 use std::thread;
 
-extern "system" {
-    fn WaitForSingleObject(handle: isize, timeout: u32) -> u32;
-}
-
-const INFINITE: u32 = u32::MAX;
+use windows_sys::Win32::Foundation::{HANDLE, WAIT_OBJECT_0};
+use windows_sys::Win32::System::Threading::{WaitForSingleObject, INFINITE};
 
 // XXX HACK: This is how miri represents the handle for thread 0.
 // This value can be "legitimately" obtained by using `GetCurrentThread` with `DuplicateHandle`
 // but miri does not implement `DuplicateHandle` yet.
-const MAIN_THREAD: isize = (2i32 << 30) as isize;
+const MAIN_THREAD: HANDLE = (2i32 << 30) as HANDLE;
 
 fn main() {
     thread::spawn(|| {
         unsafe {
-            assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), 0); //~ ERROR: deadlock: the evaluated program deadlocked
+            assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), WAIT_OBJECT_0); //~ ERROR: deadlock: the evaluated program deadlocked
         }
     })
     .join()
diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_main.stderr b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr
index 94fe95a0bdf..cb51c7e0bd9 100644
--- a/src/tools/miri/tests/fail/concurrency/windows_join_main.stderr
+++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_main.stderr
@@ -1,8 +1,8 @@
 error: deadlock: the evaluated program deadlocked
   --> $DIR/windows_join_main.rs:LL:CC
    |
-LL |             assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), 0);
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program deadlocked
+LL |             assert_eq!(WaitForSingleObject(MAIN_THREAD, INFINITE), WAIT_OBJECT_0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program deadlocked
    |
    = note: inside closure at RUSTLIB/core/src/macros/mod.rs:LL:CC
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_self.rs b/src/tools/miri/tests/fail-dep/concurrency/windows_join_self.rs
index d9bbf66a7dc..a7c8faf5a98 100644
--- a/src/tools/miri/tests/fail/concurrency/windows_join_self.rs
+++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_self.rs
@@ -6,18 +6,14 @@
 
 use std::thread;
 
-extern "system" {
-    fn GetCurrentThread() -> usize;
-    fn WaitForSingleObject(handle: usize, timeout: u32) -> u32;
-}
-
-const INFINITE: u32 = u32::MAX;
+use windows_sys::Win32::Foundation::WAIT_OBJECT_0;
+use windows_sys::Win32::System::Threading::{GetCurrentThread, WaitForSingleObject, INFINITE};
 
 fn main() {
     thread::spawn(|| {
         unsafe {
             let native = GetCurrentThread();
-            assert_eq!(WaitForSingleObject(native, INFINITE), 0); //~ ERROR: deadlock: the evaluated program deadlocked
+            assert_eq!(WaitForSingleObject(native, INFINITE), WAIT_OBJECT_0); //~ ERROR: deadlock: the evaluated program deadlocked
         }
     })
     .join()
diff --git a/src/tools/miri/tests/fail/concurrency/windows_join_self.stderr b/src/tools/miri/tests/fail-dep/concurrency/windows_join_self.stderr
index 0d2a22677c7..8b76e124215 100644
--- a/src/tools/miri/tests/fail/concurrency/windows_join_self.stderr
+++ b/src/tools/miri/tests/fail-dep/concurrency/windows_join_self.stderr
@@ -1,7 +1,7 @@
 error: deadlock: the evaluated program deadlocked
   --> $DIR/windows_join_self.rs:LL:CC
    |
-LL |             assert_eq!(WaitForSingleObject(native, INFINITE), 0);
+LL |             assert_eq!(WaitForSingleObject(native, INFINITE), WAIT_OBJECT_0);
    |                                                            ^ the evaluated program deadlocked
    |
    = note: inside closure at $DIR/windows_join_self.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs
index e79bd70e915..8a5c10913b4 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs
@@ -14,7 +14,7 @@ fn main() {
             let ptr = std::ptr::addr_of_mut!(non_copy);
             // Inside `callee`, the first argument and `*ptr` are basically
             // aliasing places!
-            Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue())
+            Call(_unit = callee(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
         }
         after_call = {
             Return()
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
index 1756123c84e..422dc243436 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
@@ -27,8 +27,8 @@ LL |     unsafe { ptr.write(S(0)) };
 note: inside `main`
   --> $DIR/arg_inplace_mutate.rs:LL:CC
    |
-LL |             Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = callee(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
index 76f7ee189e3..4fe9b7b4728 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
@@ -35,8 +35,8 @@ LL |     unsafe { ptr.write(S(0)) };
 note: inside `main`
   --> $DIR/arg_inplace_mutate.rs:LL:CC
    |
-LL |             Call(_unit = callee(Move(*ptr), ptr), after_call, UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = callee(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs
index e4c00fdd845..18daf9497a1 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs
@@ -11,7 +11,7 @@ fn main() {
         {
             let non_copy = S(42);
             // This could change `non_copy` in-place
-            Call(_unit = change_arg(Move(non_copy)), after_call, UnwindContinue())
+            Call(_unit = change_arg(Move(non_copy)), ReturnTo(after_call), UnwindContinue())
         }
         after_call = {
             // So now we must not be allowed to observe non-copy again.
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr
index 723ca75daef..1c73577f5cd 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr
@@ -11,8 +11,8 @@ LL |     unsafe { ptr.read() };
 note: inside `main`
   --> $DIR/arg_inplace_observe_during.rs:LL:CC
    |
-LL |             Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs
index 517abd733a9..2201bf17bfc 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs
@@ -14,7 +14,7 @@ fn main() {
             let non_copy = S(42);
             let ptr = std::ptr::addr_of_mut!(non_copy);
             // This could change `non_copy` in-place
-            Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue())
+            Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
         }
         after_call = {
             Return()
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
index 401e8c6d5a8..09c9a777eca 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
@@ -27,8 +27,8 @@ LL |     x.0 = 0;
 note: inside `main`
   --> $DIR/arg_inplace_observe_during.rs:LL:CC
    |
-LL |             Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
index 3529ddd3c53..67906f24bbd 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
@@ -35,8 +35,8 @@ LL |     x.0 = 0;
 note: inside `main`
   --> $DIR/arg_inplace_observe_during.rs:LL:CC
    |
-LL |             Call(_unit = change_arg(Move(*ptr), ptr), after_call, UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = change_arg(Move(*ptr), ptr), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr
index 48db898a250..eb215a2d2e8 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr
@@ -11,8 +11,8 @@ LL |     unsafe { ptr.read() };
 note: inside `main`
   --> $DIR/return_pointer_aliasing.rs:LL:CC
    |
-LL |             Call(*ptr = myfun(ptr), after_call, UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs
index 23b1e38b99f..c8e0782eff2 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs
@@ -15,7 +15,7 @@ pub fn main() {
             let ptr = &raw mut x;
             // We arrange for `myfun` to have a pointer that aliases
             // its return place. Even just reading from that pointer is UB.
-            Call(*ptr = myfun(ptr), after_call, UnwindContinue())
+            Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
         }
 
         after_call = {
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr
index 85dcd29ba55..01357f430fc 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr
@@ -27,8 +27,8 @@ LL |     unsafe { ptr.read() };
 note: inside `main`
   --> $DIR/return_pointer_aliasing.rs:LL:CC
    |
-LL |             Call(*ptr = myfun(ptr), after_call, UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr
index ea1867b1a71..6b3f5fbedee 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr
@@ -35,8 +35,8 @@ LL |     unsafe { ptr.read() };
 note: inside `main`
   --> $DIR/return_pointer_aliasing.rs:LL:CC
    |
-LL |             Call(*ptr = myfun(ptr), after_call, UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(*ptr = myfun(ptr), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs
index 56706cdb63b..7db641538ce 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs
@@ -15,7 +15,7 @@ pub fn main() {
             let ptr = &raw mut _x;
             // We arrange for `myfun` to have a pointer that aliases
             // its return place. Even just reading from that pointer is UB.
-            Call(_x = myfun(ptr), after_call, UnwindContinue())
+            Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
         }
 
         after_call = {
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr
index 12a99fbf293..04040827b0f 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stack.stderr
@@ -30,8 +30,8 @@ LL |     unsafe { ptr.write(0) };
 note: inside `main`
   --> $DIR/return_pointer_aliasing2.rs:LL:CC
    |
-LL |             Call(_x = myfun(ptr), after_call, UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr
index 926303bb489..37c98eabbec 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.tree.stderr
@@ -35,8 +35,8 @@ LL |     unsafe { ptr.write(0) };
 note: inside `main`
   --> $DIR/return_pointer_aliasing2.rs:LL:CC
    |
-LL |             Call(_x = myfun(ptr), after_call, UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_x = myfun(ptr), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs
index 923c59e7429..244acd8f2be 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_on_unwind.rs
@@ -14,7 +14,7 @@ struct S(i32, [u8; 128]);
 fn docall(out: &mut S) {
     mir! {
         {
-            Call(*out = callee(), after_call, UnwindContinue())
+            Call(*out = callee(), ReturnTo(after_call), UnwindContinue())
         }
 
         after_call = {
@@ -37,7 +37,7 @@ fn callee() -> S {
             // become visible to the outside. In codegen we can see them
             // but Miri should detect this as UB!
             RET.0 = 42;
-            Call(_unit = startpanic(), after_call, UnwindContinue())
+            Call(_unit = startpanic(), ReturnTo(after_call), UnwindContinue())
         }
 
         after_call = {
diff --git a/src/tools/miri/tests/fail/fast_math_both.rs b/src/tools/miri/tests/fail/intrinsics/fast_math_both.rs
index dd2787bf40f..dd2787bf40f 100644
--- a/src/tools/miri/tests/fail/fast_math_both.rs
+++ b/src/tools/miri/tests/fail/intrinsics/fast_math_both.rs
diff --git a/src/tools/miri/tests/fail/fast_math_both.stderr b/src/tools/miri/tests/fail/intrinsics/fast_math_both.stderr
index feba0c5991c..feba0c5991c 100644
--- a/src/tools/miri/tests/fail/fast_math_both.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/fast_math_both.stderr
diff --git a/src/tools/miri/tests/fail/fast_math_first.rs b/src/tools/miri/tests/fail/intrinsics/fast_math_first.rs
index e495498ab28..e495498ab28 100644
--- a/src/tools/miri/tests/fail/fast_math_first.rs
+++ b/src/tools/miri/tests/fail/intrinsics/fast_math_first.rs
diff --git a/src/tools/miri/tests/fail/fast_math_first.stderr b/src/tools/miri/tests/fail/intrinsics/fast_math_first.stderr
index b26b5a37215..b26b5a37215 100644
--- a/src/tools/miri/tests/fail/fast_math_first.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/fast_math_first.stderr
diff --git a/src/tools/miri/tests/fail/intrinsics/fast_math_result.rs b/src/tools/miri/tests/fail/intrinsics/fast_math_result.rs
new file mode 100644
index 00000000000..4a143da0575
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/fast_math_result.rs
@@ -0,0 +1,7 @@
+#![feature(core_intrinsics)]
+
+fn main() {
+    unsafe {
+        let _x: f32 = core::intrinsics::fdiv_fast(1.0, 0.0); //~ ERROR: `fdiv_fast` intrinsic produced non-finite value as result
+    }
+}
diff --git a/src/tools/miri/tests/fail/intrinsics/fast_math_result.stderr b/src/tools/miri/tests/fail/intrinsics/fast_math_result.stderr
new file mode 100644
index 00000000000..5b24d225026
--- /dev/null
+++ b/src/tools/miri/tests/fail/intrinsics/fast_math_result.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: `fdiv_fast` intrinsic produced non-finite value as result
+  --> $DIR/fast_math_result.rs:LL:CC
+   |
+LL |         let _x: f32 = core::intrinsics::fdiv_fast(1.0, 0.0);
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `fdiv_fast` intrinsic produced non-finite value as result
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/fast_math_result.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/fast_math_second.rs b/src/tools/miri/tests/fail/intrinsics/fast_math_second.rs
index 408c461077f..408c461077f 100644
--- a/src/tools/miri/tests/fail/fast_math_second.rs
+++ b/src/tools/miri/tests/fail/intrinsics/fast_math_second.rs
diff --git a/src/tools/miri/tests/fail/fast_math_second.stderr b/src/tools/miri/tests/fail/intrinsics/fast_math_second.stderr
index cb46aa97a8d..cb46aa97a8d 100644
--- a/src/tools/miri/tests/fail/fast_math_second.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/fast_math_second.stderr
diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs
index 9357b372505..3a87bb78677 100644
--- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs
+++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.rs
@@ -20,7 +20,7 @@ fn call(f: fn(NonZeroU32)) {
             let tmp = ptr::addr_of!(c);
             let ptr = tmp as *const NonZeroU32;
             // The call site now is a NonZeroU32-to-u32 transmute.
-            Call(_res = f(*ptr), retblock, UnwindContinue()) //~ERROR: expected something greater or equal to 1
+            Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue()) //~ERROR: expected something greater or equal to 1
         }
         retblock = {
             Return()
diff --git a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr
index 9e9ea710f0e..b1a2bd2c79a 100644
--- a/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr
+++ b/src/tools/miri/tests/fail/validity/cast_fn_ptr_invalid_caller_arg.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: constructing invalid value: encountered 0, but expected something greater or equal to 1
   --> $DIR/cast_fn_ptr_invalid_caller_arg.rs:LL:CC
    |
-LL |             Call(_res = f(*ptr), retblock, UnwindContinue())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
+LL |             Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0, but expected something greater or equal to 1
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs b/src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.rs
index 3b27af9094c..5bff9098a58 100644
--- a/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.rs
+++ b/src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.rs
@@ -2,39 +2,30 @@
 // We are making scheduler assumptions here.
 //@compile-flags: -Zmiri-preemption-rate=0
 
-use std::ffi::c_void;
 use std::ptr::null_mut;
 use std::thread;
 
+use windows_sys::Win32::System::Threading::{
+    AcquireSRWLockExclusive, AcquireSRWLockShared, ReleaseSRWLockExclusive, ReleaseSRWLockShared,
+    SleepConditionVariableSRW, WakeAllConditionVariable, CONDITION_VARIABLE,
+    CONDITION_VARIABLE_LOCKMODE_SHARED, INFINITE, SRWLOCK,
+};
+
+// not in windows-sys
+const SRWLOCK_INIT: SRWLOCK = SRWLOCK { Ptr: null_mut() };
+const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = CONDITION_VARIABLE { Ptr: null_mut() };
+
 #[derive(Copy, Clone)]
 struct SendPtr<T>(*mut T);
 
 unsafe impl<T> Send for SendPtr<T> {}
 
-extern "system" {
-    fn SleepConditionVariableSRW(
-        condvar: *mut *mut c_void,
-        lock: *mut *mut c_void,
-        timeout: u32,
-        flags: u32,
-    ) -> i32;
-    fn WakeAllConditionVariable(condvar: *mut *mut c_void);
-
-    fn AcquireSRWLockExclusive(lock: *mut *mut c_void);
-    fn AcquireSRWLockShared(lock: *mut *mut c_void);
-    fn ReleaseSRWLockExclusive(lock: *mut *mut c_void);
-    fn ReleaseSRWLockShared(lock: *mut *mut c_void);
-}
-
-const CONDITION_VARIABLE_LOCKMODE_SHARED: u32 = 1;
-const INFINITE: u32 = u32::MAX;
-
 /// threads should be able to reacquire the lock while it is locked by multiple other threads in shared mode
 fn all_shared() {
     println!("all_shared");
 
-    let mut lock = null_mut();
-    let mut condvar = null_mut();
+    let mut lock = SRWLOCK_INIT;
+    let mut condvar = CONDITION_VARIABLE_INIT;
 
     let lock_ptr = SendPtr(&mut lock);
     let condvar_ptr = SendPtr(&mut condvar);
@@ -105,8 +96,8 @@ fn all_shared() {
 fn shared_sleep_and_exclusive_lock() {
     println!("shared_sleep_and_exclusive_lock");
 
-    let mut lock = null_mut();
-    let mut condvar = null_mut();
+    let mut lock = SRWLOCK_INIT;
+    let mut condvar = CONDITION_VARIABLE_INIT;
 
     let lock_ptr = SendPtr(&mut lock);
     let condvar_ptr = SendPtr(&mut condvar);
@@ -166,8 +157,8 @@ fn shared_sleep_and_exclusive_lock() {
 fn exclusive_sleep_and_shared_lock() {
     println!("exclusive_sleep_and_shared_lock");
 
-    let mut lock = null_mut();
-    let mut condvar = null_mut();
+    let mut lock = SRWLOCK_INIT;
+    let mut condvar = CONDITION_VARIABLE_INIT;
 
     let lock_ptr = SendPtr(&mut lock);
     let condvar_ptr = SendPtr(&mut condvar);
diff --git a/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.stdout b/src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.stdout
index 918b54668f2..918b54668f2 100644
--- a/src/tools/miri/tests/pass/concurrency/windows_condvar_shared.stdout
+++ b/src/tools/miri/tests/pass-dep/concurrency/windows_condvar_shared.stdout
diff --git a/src/tools/miri/tests/pass/concurrency/windows_detach_terminated.rs b/src/tools/miri/tests/pass-dep/concurrency/windows_detach_terminated.rs
index 91088ce6aef..3d4f8c5e1c0 100644
--- a/src/tools/miri/tests/pass/concurrency/windows_detach_terminated.rs
+++ b/src/tools/miri/tests/pass-dep/concurrency/windows_detach_terminated.rs
@@ -5,12 +5,10 @@
 use std::os::windows::io::IntoRawHandle;
 use std::thread;
 
-extern "system" {
-    fn CloseHandle(handle: usize) -> i32;
-}
+use windows_sys::Win32::Foundation::{CloseHandle, HANDLE};
 
 fn main() {
-    let thread = thread::spawn(|| {}).into_raw_handle() as usize;
+    let thread = thread::spawn(|| {}).into_raw_handle() as HANDLE;
 
     // this yield ensures that `thread` is terminated by this point
     thread::yield_now();
diff --git a/src/tools/miri/tests/pass/concurrency/windows_init_once.rs b/src/tools/miri/tests/pass-dep/concurrency/windows_init_once.rs
index b2412f7dbb0..5e33617f98a 100644
--- a/src/tools/miri/tests/pass/concurrency/windows_init_once.rs
+++ b/src/tools/miri/tests/pass-dep/concurrency/windows_init_once.rs
@@ -2,33 +2,24 @@
 // We are making scheduler assumptions here.
 //@compile-flags: -Zmiri-preemption-rate=0
 
-use std::ffi::c_void;
 use std::ptr::null_mut;
 use std::thread;
 
+use windows_sys::Win32::Foundation::{FALSE, TRUE};
+use windows_sys::Win32::System::Threading::{
+    InitOnceBeginInitialize, InitOnceComplete, INIT_ONCE, INIT_ONCE_INIT_FAILED,
+};
+
+// not in windows-sys
+const INIT_ONCE_STATIC_INIT: INIT_ONCE = INIT_ONCE { Ptr: null_mut() };
+
 #[derive(Copy, Clone)]
 struct SendPtr<T>(*mut T);
 
 unsafe impl<T> Send for SendPtr<T> {}
 
-extern "system" {
-    fn InitOnceBeginInitialize(
-        init: *mut *mut c_void,
-        flags: u32,
-        pending: *mut i32,
-        context: *mut c_void,
-    ) -> i32;
-
-    fn InitOnceComplete(init: *mut *mut c_void, flags: u32, context: *mut c_void) -> i32;
-}
-
-const TRUE: i32 = 1;
-const FALSE: i32 = 0;
-
-const INIT_ONCE_INIT_FAILED: u32 = 4;
-
 fn single_thread() {
-    let mut init_once = null_mut();
+    let mut init_once = INIT_ONCE_STATIC_INIT;
     let mut pending = 0;
 
     unsafe {
@@ -41,7 +32,7 @@ fn single_thread() {
         assert_eq!(pending, FALSE);
     }
 
-    let mut init_once = null_mut();
+    let mut init_once = INIT_ONCE_STATIC_INIT;
 
     unsafe {
         assert_eq!(InitOnceBeginInitialize(&mut init_once, 0, &mut pending, null_mut()), TRUE);
@@ -55,7 +46,7 @@ fn single_thread() {
 }
 
 fn block_until_complete() {
-    let mut init_once = null_mut();
+    let mut init_once = INIT_ONCE_STATIC_INIT;
     let mut pending = 0;
 
     unsafe {
@@ -92,7 +83,7 @@ fn block_until_complete() {
 }
 
 fn retry_on_fail() {
-    let mut init_once = null_mut();
+    let mut init_once = INIT_ONCE_STATIC_INIT;
     let mut pending = 0;
 
     unsafe {
@@ -134,7 +125,7 @@ fn retry_on_fail() {
 }
 
 fn no_data_race_after_complete() {
-    let mut init_once = null_mut();
+    let mut init_once = INIT_ONCE_STATIC_INIT;
     let mut pending = 0;
 
     unsafe {
diff --git a/src/tools/miri/tests/pass/concurrency/windows_init_once.stdout b/src/tools/miri/tests/pass-dep/concurrency/windows_init_once.stdout
index f3d5aad8edc..f3d5aad8edc 100644
--- a/src/tools/miri/tests/pass/concurrency/windows_init_once.stdout
+++ b/src/tools/miri/tests/pass-dep/concurrency/windows_init_once.stdout
diff --git a/src/tools/miri/tests/pass/concurrency/windows_join_multiple.rs b/src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs
index 5da5497f982..bff59591a94 100644
--- a/src/tools/miri/tests/pass/concurrency/windows_join_multiple.rs
+++ b/src/tools/miri/tests/pass-dep/concurrency/windows_join_multiple.rs
@@ -6,11 +6,8 @@ use std::os::windows::io::IntoRawHandle;
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::thread;
 
-extern "system" {
-    fn WaitForSingleObject(handle: usize, timeout: u32) -> u32;
-}
-
-const INFINITE: u32 = u32::MAX;
+use windows_sys::Win32::Foundation::{HANDLE, WAIT_OBJECT_0};
+use windows_sys::Win32::System::Threading::{WaitForSingleObject, INFINITE};
 
 fn main() {
     static FLAG: AtomicBool = AtomicBool::new(false);
@@ -20,10 +17,10 @@ fn main() {
             thread::yield_now();
         }
     })
-    .into_raw_handle() as usize;
+    .into_raw_handle() as HANDLE;
 
     let waiter = move || unsafe {
-        assert_eq!(WaitForSingleObject(blocker, INFINITE), 0);
+        assert_eq!(WaitForSingleObject(blocker, INFINITE), WAIT_OBJECT_0);
     };
 
     let waiter1 = thread::spawn(waiter);
diff --git a/src/tools/miri/tests/pass-dep/shims/mmap.rs b/src/tools/miri/tests/pass-dep/shims/mmap.rs
index 518f2ea3e6f..e19f54d0687 100644
--- a/src/tools/miri/tests/pass-dep/shims/mmap.rs
+++ b/src/tools/miri/tests/pass-dep/shims/mmap.rs
@@ -90,9 +90,30 @@ fn test_mmap() {
         assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::ENOTSUP);
     }
 
+    // We report an error for mappings whose length cannot be rounded up to a multiple of
+    // the page size.
+    let ptr = unsafe {
+        libc::mmap(
+            ptr::null_mut(),
+            usize::MAX - 1,
+            libc::PROT_READ | libc::PROT_WRITE,
+            libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
+            -1,
+            0,
+        )
+    };
+    assert_eq!(ptr, libc::MAP_FAILED);
+
+    // We report an error when trying to munmap an address which is not a multiple of the page size
     let res = unsafe { libc::munmap(ptr::invalid_mut(1), page_size) };
     assert_eq!(res, -1);
     assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::EINVAL);
+
+    // We report an error when trying to munmap a length that cannot be rounded up to a multiple of
+    // the page size.
+    let res = unsafe { libc::munmap(ptr::invalid_mut(page_size), usize::MAX - 1) };
+    assert_eq!(res, -1);
+    assert_eq!(Error::last_os_error().raw_os_error().unwrap(), libc::EINVAL);
 }
 
 #[cfg(target_os = "linux")]
diff --git a/src/tools/miri/tests/pass-dep/tempfile.rs b/src/tools/miri/tests/pass-dep/tempfile.rs
new file mode 100644
index 00000000000..c4583ca3f47
--- /dev/null
+++ b/src/tools/miri/tests/pass-dep/tempfile.rs
@@ -0,0 +1,21 @@
+//@ignore-target-windows: File handling is not implemented yet
+//@ignore-host-windows: Only supported for UNIX hosts
+//@compile-flags: -Zmiri-disable-isolation
+
+#[path = "../utils/mod.rs"]
+mod utils;
+
+/// Test that the [`tempfile`] crate is compatible with miri for UNIX hosts and targets
+fn main() {
+    test_tempfile();
+    test_tempfile_in();
+}
+
+fn test_tempfile() {
+    tempfile::tempfile().unwrap();
+}
+
+fn test_tempfile_in() {
+    let dir_path = utils::tmp();
+    tempfile::tempfile_in(dir_path).unwrap();
+}
diff --git a/src/tools/miri/tests/pass/float_nan.rs b/src/tools/miri/tests/pass/float_nan.rs
index 6ea034e2cda..207ce70fb20 100644
--- a/src/tools/miri/tests/pass/float_nan.rs
+++ b/src/tools/miri/tests/pass/float_nan.rs
@@ -1,8 +1,16 @@
+#![feature(float_gamma, portable_simd, core_intrinsics, platform_intrinsics)]
 use std::collections::HashSet;
 use std::fmt;
 use std::hash::Hash;
 use std::hint::black_box;
 
+fn ldexp(a: f64, b: i32) -> f64 {
+    extern "C" {
+        fn ldexp(x: f64, n: i32) -> f64;
+    }
+    unsafe { ldexp(a, b) }
+}
+
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 enum Sign {
     Neg = 1,
@@ -249,6 +257,58 @@ fn test_f32() {
     check_all_outcomes(HashSet::from_iter([F32::nan(Neg, Signaling, all1_payload)]), || {
         F32::from(-all1_snan)
     });
+
+    // Intrinsics
+    let nan = F32::nan(Neg, Quiet, 0).as_f32();
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(f32::min(nan, nan)),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(nan.sin()),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([
+            F32::nan(Pos, Quiet, 0),
+            F32::nan(Neg, Quiet, 0),
+            F32::nan(Pos, Quiet, 1),
+            F32::nan(Neg, Quiet, 1),
+            F32::nan(Pos, Quiet, 2),
+            F32::nan(Neg, Quiet, 2),
+            F32::nan(Pos, Quiet, all1_payload),
+            F32::nan(Neg, Quiet, all1_payload),
+            F32::nan(Pos, Signaling, all1_payload),
+            F32::nan(Neg, Signaling, all1_payload),
+        ]),
+        || F32::from(just1.mul_add(F32::nan(Neg, Quiet, 2).as_f32(), all1_snan)),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(nan.powf(nan)),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([1.0f32.into()]),
+        || F32::from(1.0f32.powf(nan)), // special `pow` rule
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(nan.powi(1)),
+    );
+
+    // libm functions
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(nan.sinh()),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(nan.atan2(nan)),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(nan.ln_gamma().0),
+    );
 }
 
 fn test_f64() {
@@ -309,6 +369,62 @@ fn test_f64() {
         ]),
         || F64::from(just1 % all1_snan),
     );
+
+    // Intrinsics
+    let nan = F64::nan(Neg, Quiet, 0).as_f64();
+    check_all_outcomes(
+        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
+        || F64::from(f64::min(nan, nan)),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
+        || F64::from(nan.sin()),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([
+            F64::nan(Pos, Quiet, 0),
+            F64::nan(Neg, Quiet, 0),
+            F64::nan(Pos, Quiet, 1),
+            F64::nan(Neg, Quiet, 1),
+            F64::nan(Pos, Quiet, 2),
+            F64::nan(Neg, Quiet, 2),
+            F64::nan(Pos, Quiet, all1_payload),
+            F64::nan(Neg, Quiet, all1_payload),
+            F64::nan(Pos, Signaling, all1_payload),
+            F64::nan(Neg, Signaling, all1_payload),
+        ]),
+        || F64::from(just1.mul_add(F64::nan(Neg, Quiet, 2).as_f64(), all1_snan)),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
+        || F64::from(nan.powf(nan)),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([1.0f64.into()]),
+        || F64::from(1.0f64.powf(nan)), // special `pow` rule
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
+        || F64::from(nan.powi(1)),
+    );
+
+    // libm functions
+    check_all_outcomes(
+        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
+        || F64::from(nan.sinh()),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
+        || F64::from(nan.atan2(nan)),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
+        || F64::from(ldexp(nan, 1)),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
+        || F64::from(nan.ln_gamma().0),
+    );
 }
 
 fn test_casts() {
@@ -397,6 +513,61 @@ fn test_casts() {
     );
 }
 
+fn test_simd() {
+    use std::intrinsics::simd::*;
+    use std::simd::*;
+
+    extern "platform-intrinsic" {
+        fn simd_fsqrt<T>(x: T) -> T;
+        fn simd_ceil<T>(x: T) -> T;
+        fn simd_fma<T>(x: T, y: T, z: T) -> T;
+    }
+
+    let nan = F32::nan(Neg, Quiet, 0).as_f32();
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(unsafe { simd_div(f32x4::splat(0.0), f32x4::splat(0.0)) }[0]),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(unsafe { simd_fmin(f32x4::splat(nan), f32x4::splat(nan)) }[0]),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(unsafe { simd_fmax(f32x4::splat(nan), f32x4::splat(nan)) }[0]),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || {
+            F32::from(
+                unsafe { simd_fma(f32x4::splat(nan), f32x4::splat(nan), f32x4::splat(nan)) }[0],
+            )
+        },
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(unsafe { simd_reduce_add_ordered::<_, f32>(f32x4::splat(nan), nan) }),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(unsafe { simd_reduce_max::<_, f32>(f32x4::splat(nan)) }),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(unsafe { simd_fsqrt(f32x4::splat(nan)) }[0]),
+    );
+    check_all_outcomes(
+        HashSet::from_iter([F32::nan(Pos, Quiet, 0), F32::nan(Neg, Quiet, 0)]),
+        || F32::from(unsafe { simd_ceil(f32x4::splat(nan)) }[0]),
+    );
+
+    // Casts
+    check_all_outcomes(
+        HashSet::from_iter([F64::nan(Pos, Quiet, 0), F64::nan(Neg, Quiet, 0)]),
+        || F64::from(unsafe { simd_cast::<f32x4, f64x4>(f32x4::splat(nan)) }[0]),
+    );
+}
+
 fn main() {
     // Check our constants against std, just to be sure.
     // We add 1 since our numbers are the number of bits stored
@@ -408,4 +579,5 @@ fn main() {
     test_f32();
     test_f64();
     test_casts();
+    test_simd();
 }
diff --git a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs
index 89ee689fabe..a5cbe2a0d1d 100644
--- a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs
+++ b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs
@@ -11,7 +11,7 @@ pub fn main() {
         {
             let x = 0;
             let ptr = &raw mut x;
-            Call(*ptr = myfun(), after_call, UnwindContinue())
+            Call(*ptr = myfun(), ReturnTo(after_call), UnwindContinue())
         }
 
         after_call = {