From a84e93d562ba5586a89e078f8d718f27d8920d83 Mon Sep 17 00:00:00 2001 From: Erin Date: Mon, 15 Jan 2024 17:51:08 +0100 Subject: [PATCH] idk --- hbvm/src/float/x86_64.rs | 43 ++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 26 deletions(-) diff --git a/hbvm/src/float/x86_64.rs b/hbvm/src/float/x86_64.rs index 468aabe..e899f20 100644 --- a/hbvm/src/float/x86_64.rs +++ b/hbvm/src/float/x86_64.rs @@ -30,9 +30,24 @@ macro_rules! fnsdef { $vis fn $name(val: $from, mode: RoundingMode) -> $to { let result: $to; unsafe { - set_rounding_mode(mode); + let mut mxcsr = 0_u32; + 'a: { + asm!("stmxcsr {}", in(reg) &mut mxcsr); + asm!( + "ldmxcsr {}", + in(reg) &(mxcsr & !arin::_MM_ROUND_MASK | match mode { + RoundingMode::NearestEven => break 'a, + RoundingMode::Truncate => arin::_MM_ROUND_TOWARD_ZERO, + RoundingMode::Up => arin::_MM_ROUND_UP, + RoundingMode::Down => arin::_MM_ROUND_DOWN, + }) + ); + } + op!($ins, val, result => $to); - default_rounding_mode(); + + // Set MXCSR to original value + asm!("ldmxcsr {}", in(reg) &mxcsr); } result } @@ -47,27 +62,3 @@ fnsdef! { /// Convert [`f64`] to [`i64`] with chosen rounding mode pub fn f64toint(f64 -> i64): "cvttsd2si"; } - -/// Set rounding mode -/// -/// # Safety -/// - Do not call if rounding mode isn't [`RoundingMode::NearestEven`] -/// - Do not perform any Rust FP operations until reset using -/// [`default_rounding_mode`], you have to rely on inline assembly -#[inline(always)] -unsafe fn set_rounding_mode(mode: RoundingMode) { - unsafe { - arin::_MM_SET_ROUNDING_MODE(match mode { - RoundingMode::NearestEven => return, - RoundingMode::Truncate => arin::_MM_ROUND_TOWARD_ZERO, - RoundingMode::Up => arin::_MM_ROUND_UP, - RoundingMode::Down => arin::_MM_ROUND_DOWN, - }) - } -} - -#[inline(always)] -fn default_rounding_mode() { - // SAFETY: This is said to be the default mode, do not trust me. - unsafe { arin::_MM_SET_ROUNDING_MODE(arin::_MM_ROUND_NEAREST) }; -}