Prechádzať zdrojové kódy

Convert float intrinsics to the `intrinsics!` macro

Alex Crichton 7 rokov pred
rodič
commit
83d63eaa9b
6 zmenil súbory, kde vykonal 349 pridanie a 356 odobranie
  1. 161 163
      src/float/add.rs
  2. 143 95
      src/float/conv.rs
  3. 28 24
      src/float/pow.rs
  4. 7 16
      src/float/sub.rs
  5. 10 12
      src/int/udiv.rs
  6. 0 46
      src/lib.rs

+ 161 - 163
src/float/add.rs

@@ -3,192 +3,190 @@ use core::num::Wrapping;
 
 use float::Float;
 
+/// Returns `a + b`
 macro_rules! add {
-    ($abi:tt, $intrinsic:ident: $ty:ty) => {
-        /// Returns `a + b`
-        #[allow(unused_parens)]
-        #[cfg_attr(not(test), no_mangle)]
-        pub extern $abi fn $intrinsic(a: $ty, b: $ty) -> $ty {
-            let one = Wrapping(1 as <$ty as Float>::Int);
-            let zero = Wrapping(0 as <$ty as Float>::Int);
-
-            let bits =             Wrapping(<$ty>::bits() as <$ty as Float>::Int);
-            let significand_bits = Wrapping(<$ty>::significand_bits() as <$ty as Float>::Int);
-            let exponent_bits =    bits - significand_bits - one;
-            let max_exponent =     (one << exponent_bits.0 as usize) - one;
-
-            let implicit_bit =     one << significand_bits.0 as usize;
-            let significand_mask = implicit_bit - one;
-            let sign_bit =         one << (significand_bits + exponent_bits).0 as usize;
-            let abs_mask =         sign_bit - one;
-            let exponent_mask =    abs_mask ^ significand_mask;
-            let inf_rep =          exponent_mask;
-            let quiet_bit =        implicit_bit >> 1;
-            let qnan_rep =         exponent_mask | quiet_bit;
-
-            let mut a_rep = Wrapping(a.repr());
-            let mut b_rep = Wrapping(b.repr());
-            let a_abs = a_rep & abs_mask;
-            let b_abs = b_rep & abs_mask;
-
-            // Detect if a or b is zero, infinity, or NaN.
-            if a_abs - one >= inf_rep - one ||
-                b_abs - one >= inf_rep - one {
-                // NaN + anything = qNaN
-                if a_abs > inf_rep {
-                    return (<$ty as Float>::from_repr((a_abs | quiet_bit).0));
-                }
-                // anything + NaN = qNaN
-                if b_abs > inf_rep {
-                    return (<$ty as Float>::from_repr((b_abs | quiet_bit).0));
-                }
-
-                if a_abs == inf_rep {
-                    // +/-infinity + -/+infinity = qNaN
-                    if (a.repr() ^ b.repr()) == sign_bit.0 {
-                        return (<$ty as Float>::from_repr(qnan_rep.0));
-                    } else {
-                        // +/-infinity + anything remaining = +/- infinity
-                        return a;
-                    }
-                }
+    ($a:expr, $b:expr, $ty:ty) => ({
+        let a = $a;
+        let b = $b;
+        let one = Wrapping(1 as <$ty as Float>::Int);
+        let zero = Wrapping(0 as <$ty as Float>::Int);
+
+        let bits =             Wrapping(<$ty>::bits() as <$ty as Float>::Int);
+        let significand_bits = Wrapping(<$ty>::significand_bits() as <$ty as Float>::Int);
+        let exponent_bits =    bits - significand_bits - one;
+        let max_exponent =     (one << exponent_bits.0 as usize) - one;
+
+        let implicit_bit =     one << significand_bits.0 as usize;
+        let significand_mask = implicit_bit - one;
+        let sign_bit =         one << (significand_bits + exponent_bits).0 as usize;
+        let abs_mask =         sign_bit - one;
+        let exponent_mask =    abs_mask ^ significand_mask;
+        let inf_rep =          exponent_mask;
+        let quiet_bit =        implicit_bit >> 1;
+        let qnan_rep =         exponent_mask | quiet_bit;
+
+        let mut a_rep = Wrapping(a.repr());
+        let mut b_rep = Wrapping(b.repr());
+        let a_abs = a_rep & abs_mask;
+        let b_abs = b_rep & abs_mask;
+
+        // Detect if a or b is zero, infinity, or NaN.
+        if a_abs - one >= inf_rep - one ||
+            b_abs - one >= inf_rep - one {
+            // NaN + anything = qNaN
+            if a_abs > inf_rep {
+                return <$ty as Float>::from_repr((a_abs | quiet_bit).0);
+            }
+            // anything + NaN = qNaN
+            if b_abs > inf_rep {
+                return <$ty as Float>::from_repr((b_abs | quiet_bit).0);
+            }
 
-                // anything remaining + +/-infinity = +/-infinity
-                if b_abs == inf_rep {
-                    return b;
+            if a_abs == inf_rep {
+                // +/-infinity + -/+infinity = qNaN
+                if (a.repr() ^ b.repr()) == sign_bit.0 {
+                    return <$ty as Float>::from_repr(qnan_rep.0);
+                } else {
+                    // +/-infinity + anything remaining = +/- infinity
+                    return a;
                 }
+            }
 
-                // zero + anything = anything
-                if a_abs.0 == 0 {
-                    // but we need to get the sign right for zero + zero
-                    if b_abs.0 == 0 {
-                        return (<$ty as Float>::from_repr(a.repr() & b.repr()));
-                    } else {
-                        return b;
-                    }
-                }
+            // anything remaining + +/-infinity = +/-infinity
+            if b_abs == inf_rep {
+                return b;
+            }
 
-                // anything + zero = anything
+            // zero + anything = anything
+            if a_abs.0 == 0 {
+                // but we need to get the sign right for zero + zero
                 if b_abs.0 == 0 {
-                     return a;
+                    return <$ty as Float>::from_repr(a.repr() & b.repr());
+                } else {
+                    return b;
                 }
             }
 
-            // Swap a and b if necessary so that a has the larger absolute value.
-            if b_abs > a_abs {
-                mem::swap(&mut a_rep, &mut b_rep);
+            // anything + zero = anything
+            if b_abs.0 == 0 {
+                 return a;
             }
+        }
 
-            // Extract the exponent and significand from the (possibly swapped) a and b.
-            let mut a_exponent = Wrapping((a_rep >> significand_bits.0 as usize & max_exponent).0 as i32);
-            let mut b_exponent = Wrapping((b_rep >> significand_bits.0 as usize & max_exponent).0 as i32);
-            let mut a_significand = a_rep & significand_mask;
-            let mut b_significand = b_rep & significand_mask;
-
-            // normalize any denormals, and adjust the exponent accordingly.
-            if a_exponent.0 == 0 {
-                let (exponent, significand) = <$ty>::normalize(a_significand.0);
-                a_exponent = Wrapping(exponent);
-                a_significand = Wrapping(significand);
-            }
-            if b_exponent.0 == 0 {
-                let (exponent, significand) = <$ty>::normalize(b_significand.0);
-                b_exponent = Wrapping(exponent);
-                b_significand = Wrapping(significand);
-            }
+        // Swap a and b if necessary so that a has the larger absolute value.
+        if b_abs > a_abs {
+            mem::swap(&mut a_rep, &mut b_rep);
+        }
 
-            // The sign of the result is the sign of the larger operand, a.  If they
-            // have opposite signs, we are performing a subtraction; otherwise addition.
-            let result_sign = a_rep & sign_bit;
-            let subtraction = ((a_rep ^ b_rep) & sign_bit) != zero;
-
-            // Shift the significands to give us round, guard and sticky, and or in the
-            // implicit significand bit.  (If we fell through from the denormal path it
-            // was already set by normalize(), but setting it twice won't hurt
-            // anything.)
-            a_significand = (a_significand | implicit_bit) << 3;
-            b_significand = (b_significand | implicit_bit) << 3;
-
-            // Shift the significand of b by the difference in exponents, with a sticky
-            // bottom bit to get rounding correct.
-            let align = Wrapping((a_exponent - b_exponent).0 as <$ty as Float>::Int);
-            if align.0 != 0 {
-                if align < bits {
-                    let sticky = ((b_significand << (bits - align).0 as usize).0 != 0) as <$ty as Float>::Int;
-                    b_significand = (b_significand >> align.0 as usize) | Wrapping(sticky);
-                } else {
-                    b_significand = one; // sticky; b is known to be non-zero.
-                }
-            }
-            if subtraction {
-                a_significand -= b_significand;
-                // If a == -b, return +zero.
-                if a_significand.0 == 0 {
-                    return (<$ty as Float>::from_repr(0));
-                }
+        // Extract the exponent and significand from the (possibly swapped) a and b.
+        let mut a_exponent = Wrapping((a_rep >> significand_bits.0 as usize & max_exponent).0 as i32);
+        let mut b_exponent = Wrapping((b_rep >> significand_bits.0 as usize & max_exponent).0 as i32);
+        let mut a_significand = a_rep & significand_mask;
+        let mut b_significand = b_rep & significand_mask;
+
+        // normalize any denormals, and adjust the exponent accordingly.
+        if a_exponent.0 == 0 {
+            let (exponent, significand) = <$ty>::normalize(a_significand.0);
+            a_exponent = Wrapping(exponent);
+            a_significand = Wrapping(significand);
+        }
+        if b_exponent.0 == 0 {
+            let (exponent, significand) = <$ty>::normalize(b_significand.0);
+            b_exponent = Wrapping(exponent);
+            b_significand = Wrapping(significand);
+        }
 
-                // If partial cancellation occured, we need to left-shift the result
-                // and adjust the exponent:
-                if a_significand < implicit_bit << 3 {
-                    let shift = a_significand.0.leading_zeros() as i32
-                        - (implicit_bit << 3).0.leading_zeros() as i32;
-                    a_significand <<= shift as usize;
-                    a_exponent -= Wrapping(shift);
-                }
-            } else /* addition */ {
-                a_significand += b_significand;
-
-                // If the addition carried up, we need to right-shift the result and
-                // adjust the exponent:
-                if (a_significand & implicit_bit << 4).0 != 0 {
-                    let sticky = ((a_significand & one).0 != 0) as <$ty as Float>::Int;
-                    a_significand = a_significand >> 1 | Wrapping(sticky);
-                    a_exponent += Wrapping(1);
-                }
+        // The sign of the result is the sign of the larger operand, a.  If they
+        // have opposite signs, we are performing a subtraction; otherwise addition.
+        let result_sign = a_rep & sign_bit;
+        let subtraction = ((a_rep ^ b_rep) & sign_bit) != zero;
+
+        // Shift the significands to give us round, guard and sticky, and or in the
+        // implicit significand bit.  (If we fell through from the denormal path it
+        // was already set by normalize(), but setting it twice won't hurt
+        // anything.)
+        a_significand = (a_significand | implicit_bit) << 3;
+        b_significand = (b_significand | implicit_bit) << 3;
+
+        // Shift the significand of b by the difference in exponents, with a sticky
+        // bottom bit to get rounding correct.
+        let align = Wrapping((a_exponent - b_exponent).0 as <$ty as Float>::Int);
+        if align.0 != 0 {
+            if align < bits {
+                let sticky = ((b_significand << (bits - align).0 as usize).0 != 0) as <$ty as Float>::Int;
+                b_significand = (b_significand >> align.0 as usize) | Wrapping(sticky);
+            } else {
+                b_significand = one; // sticky; b is known to be non-zero.
             }
-
-            // If we have overflowed the type, return +/- infinity:
-            if a_exponent >= Wrapping(max_exponent.0 as i32) {
-                return (<$ty>::from_repr((inf_rep | result_sign).0));
+        }
+        if subtraction {
+            a_significand -= b_significand;
+            // If a == -b, return +zero.
+            if a_significand.0 == 0 {
+                return <$ty as Float>::from_repr(0);
             }
 
-            if a_exponent.0 <= 0 {
-                // Result is denormal before rounding; the exponent is zero and we
-                // need to shift the significand.
-                let shift = Wrapping((Wrapping(1) - a_exponent).0 as <$ty as Float>::Int);
-                let sticky = ((a_significand << (bits - shift).0 as usize).0 != 0) as <$ty as Float>::Int;
-                a_significand = a_significand >> shift.0 as usize | Wrapping(sticky);
-                a_exponent = Wrapping(0);
+            // If partial cancellation occured, we need to left-shift the result
+            // and adjust the exponent:
+            if a_significand < implicit_bit << 3 {
+                let shift = a_significand.0.leading_zeros() as i32
+                    - (implicit_bit << 3).0.leading_zeros() as i32;
+                a_significand <<= shift as usize;
+                a_exponent -= Wrapping(shift);
             }
+        } else /* addition */ {
+            a_significand += b_significand;
+
+            // If the addition carried up, we need to right-shift the result and
+            // adjust the exponent:
+            if (a_significand & implicit_bit << 4).0 != 0 {
+                let sticky = ((a_significand & one).0 != 0) as <$ty as Float>::Int;
+                a_significand = a_significand >> 1 | Wrapping(sticky);
+                a_exponent += Wrapping(1);
+            }
+        }
 
-            // Low three bits are round, guard, and sticky.
-            let round_guard_sticky: i32 = (a_significand.0 & 0x7) as i32;
+        // If we have overflowed the type, return +/- infinity:
+        if a_exponent >= Wrapping(max_exponent.0 as i32) {
+            return <$ty>::from_repr((inf_rep | result_sign).0);
+        }
 
-            // Shift the significand into place, and mask off the implicit bit.
-            let mut result = a_significand >> 3 & significand_mask;
+        if a_exponent.0 <= 0 {
+            // Result is denormal before rounding; the exponent is zero and we
+            // need to shift the significand.
+            let shift = Wrapping((Wrapping(1) - a_exponent).0 as <$ty as Float>::Int);
+            let sticky = ((a_significand << (bits - shift).0 as usize).0 != 0) as <$ty as Float>::Int;
+            a_significand = a_significand >> shift.0 as usize | Wrapping(sticky);
+            a_exponent = Wrapping(0);
+        }
 
-            // Insert the exponent and sign.
-            result |= Wrapping(a_exponent.0 as <$ty as Float>::Int) << significand_bits.0 as usize;
-            result |= result_sign;
+        // Low three bits are round, guard, and sticky.
+        let round_guard_sticky: i32 = (a_significand.0 & 0x7) as i32;
 
-            // Final rounding.  The result may overflow to infinity, but that is the
-            // correct result in that case.
-            if round_guard_sticky > 0x4 { result += one; }
-            if round_guard_sticky == 0x4 { result += result & one; }
+        // Shift the significand into place, and mask off the implicit bit.
+        let mut result = a_significand >> 3 & significand_mask;
 
-            <$ty>::from_repr(result.0)
-        }
-    }
-}
+        // Insert the exponent and sign.
+        result |= Wrapping(a_exponent.0 as <$ty as Float>::Int) << significand_bits.0 as usize;
+        result |= result_sign;
 
-#[cfg(target_arch = "arm")]
-add!("aapcs", __addsf3: f32);
+        // Final rounding.  The result may overflow to infinity, but that is the
+        // correct result in that case.
+        if round_guard_sticky > 0x4 { result += one; }
+        if round_guard_sticky == 0x4 { result += result & one; }
 
-#[cfg(not(target_arch = "arm"))]
-add!("C", __addsf3: f32);
+        <$ty>::from_repr(result.0)
+    })
+}
 
-#[cfg(target_arch = "arm")]
-add!("aapcs", __adddf3: f64);
+intrinsics! {
+    #[aapcs_on_arm]
+    pub extern "C" fn __addsf3(a: f32, b: f32) -> f32 {
+        add!(a, b, f32)
+    }
 
-#[cfg(not(target_arch = "arm"))]
-add!("C", __adddf3: f64);
+    #[aapcs_on_arm]
+    pub extern "C" fn __adddf3(a: f64, b: f64) -> f64 {
+        add!(a, b, f64)
+    }
+}

+ 143 - 95
src/float/conv.rs

@@ -2,12 +2,8 @@ use float::Float;
 use int::Int;
 
 macro_rules! int_to_float {
-    ($intrinsic:ident: $ity:ty, $fty:ty) => {
-        int_to_float!($intrinsic: $ity, $fty, "C");
-    };
-    ($intrinsic:ident: $ity:ty, $fty:ty, $abi:tt) => {
-
-    pub extern $abi fn $intrinsic(i: $ity) -> $fty {
+    ($i:expr, $ity:ty, $fty:ty) => ({
+        let i = $i;
         if i == 0 {
             return 0.0
         }
@@ -70,29 +66,54 @@ macro_rules! int_to_float {
         <$fty>::from_parts(s,
             (e + exponent_bias) as <$fty as Float>::Int,
             a as <$fty as Float>::Int)
+    })
+}
+
+intrinsics! {
+    pub extern "C" fn __floatsisf(i: i32) -> f32 {
+        int_to_float!(i, i32, f32)
     }
+
+    pub extern "C" fn __floatsidf(i: i32) -> f64 {
+        int_to_float!(i, i32, f64)
     }
-}
 
-macro_rules! int_to_float_unadj_on_win {
-    ($intrinsic:ident: $ity:ty, $fty:ty) => {
-        #[cfg(all(windows, target_pointer_width="64"))]
-        int_to_float!($intrinsic: $ity, $fty, "unadjusted");
-        #[cfg(not(all(windows, target_pointer_width="64")))]
-        int_to_float!($intrinsic: $ity, $fty, "C");
-    };
-}
+    pub extern "C" fn __floatdidf(i: i64) -> f64 {
+        int_to_float!(i, i64, f64)
+    }
 
-int_to_float!(__floatsisf: i32, f32);
-int_to_float!(__floatsidf: i32, f64);
-int_to_float!(__floatdidf: i64, f64);
-int_to_float_unadj_on_win!(__floattisf: i128, f32);
-int_to_float_unadj_on_win!(__floattidf: i128, f64);
-int_to_float!(__floatunsisf: u32, f32);
-int_to_float!(__floatunsidf: u32, f64);
-int_to_float!(__floatundidf: u64, f64);
-int_to_float_unadj_on_win!(__floatuntisf: u128, f32);
-int_to_float_unadj_on_win!(__floatuntidf: u128, f64);
+    #[unadjusted_on_win64]
+    pub extern "C" fn __floattisf(i: i128) -> f32 {
+        int_to_float!(i, i128, f32)
+    }
+
+    #[unadjusted_on_win64]
+    pub extern "C" fn __floattidf(i: i128) -> f64 {
+        int_to_float!(i, i128, f64)
+    }
+
+    pub extern "C" fn __floatunsisf(i: u32) -> f32 {
+        int_to_float!(i, u32, f32)
+    }
+
+    pub extern "C" fn __floatunsidf(i: u32) -> f64 {
+        int_to_float!(i, u32, f64)
+    }
+
+    pub extern "C" fn __floatundidf(i: u64) -> f64 {
+        int_to_float!(i, u64, f64)
+    }
+
+    #[unadjusted_on_win64]
+    pub extern "C" fn __floatuntisf(i: u128) -> f32 {
+        int_to_float!(i, u128, f32)
+    }
+
+    #[unadjusted_on_win64]
+    pub extern "C" fn __floatuntidf(i: u128) -> f64 {
+        int_to_float!(i, u128, f64)
+    }
+}
 
 #[derive(PartialEq, Debug)]
 enum Sign {
@@ -101,79 +122,106 @@ enum Sign {
 }
 
 macro_rules! float_to_int {
-    ($intrinsic:ident: $fty:ty, $ity:ty) => {
-        float_to_int!($intrinsic: $fty, $ity, "C");
-    };
-    ($intrinsic:ident: $fty:ty, $ity:ty, $abi:tt) => {
-        pub extern $abi fn $intrinsic(f: $fty) -> $ity {
-            let fixint_min = <$ity>::min_value();
-            let fixint_max = <$ity>::max_value();
-            let fixint_bits = <$ity>::bits() as usize;
-            let fixint_unsigned = fixint_min == 0;
-
-            let sign_bit = <$fty>::sign_mask();
-            let significand_bits = <$fty>::significand_bits() as usize;
-            let exponent_bias = <$fty>::exponent_bias() as usize;
-            //let exponent_max = <$fty>::exponent_max() as usize;
-
-            // Break a into sign, exponent, significand
-            let a_rep = <$fty>::repr(f);
-            let a_abs = a_rep & !sign_bit;
-
-            // this is used to work around -1 not being available for unsigned
-            let sign = if (a_rep & sign_bit) == 0 { Sign::Positive } else { Sign::Negative };
-            let mut exponent = (a_abs >> significand_bits) as usize;
-            let significand = (a_abs & <$fty>::significand_mask()) | <$fty>::implicit_bit();
-
-            // if < 1 or unsigned & negative
-            if  exponent < exponent_bias ||
-                fixint_unsigned && sign == Sign::Negative {
-                return 0
-            }
-            exponent -= exponent_bias;
+    ($f:expr, $fty:ty, $ity:ty) => ({
+        let f = $f;
+        let fixint_min = <$ity>::min_value();
+        let fixint_max = <$ity>::max_value();
+        let fixint_bits = <$ity>::bits() as usize;
+        let fixint_unsigned = fixint_min == 0;
+
+        let sign_bit = <$fty>::sign_mask();
+        let significand_bits = <$fty>::significand_bits() as usize;
+        let exponent_bias = <$fty>::exponent_bias() as usize;
+        //let exponent_max = <$fty>::exponent_max() as usize;
+
+        // Break a into sign, exponent, significand
+        let a_rep = <$fty>::repr(f);
+        let a_abs = a_rep & !sign_bit;
+
+        // this is used to work around -1 not being available for unsigned
+        let sign = if (a_rep & sign_bit) == 0 { Sign::Positive } else { Sign::Negative };
+        let mut exponent = (a_abs >> significand_bits) as usize;
+        let significand = (a_abs & <$fty>::significand_mask()) | <$fty>::implicit_bit();
+
+        // if < 1 or unsigned & negative
+        if  exponent < exponent_bias ||
+            fixint_unsigned && sign == Sign::Negative {
+            return 0
+        }
+        exponent -= exponent_bias;
 
-            // If the value is infinity, saturate.
-            // If the value is too large for the integer type, 0.
-            if exponent >= (if fixint_unsigned {fixint_bits} else {fixint_bits -1}) {
-                return if sign == Sign::Positive {fixint_max} else {fixint_min}
-            }
-            // If 0 <= exponent < significand_bits, right shift to get the result.
-            // Otherwise, shift left.
-            // (sign - 1) will never overflow as negative signs are already returned as 0 for unsigned
-            let r = if exponent < significand_bits {
-                (significand >> (significand_bits - exponent)) as $ity
-            } else {
-                (significand as $ity) << (exponent - significand_bits)
-            };
+        // If the value is infinity, saturate.
+        // If the value is too large for the integer type, 0.
+        if exponent >= (if fixint_unsigned {fixint_bits} else {fixint_bits -1}) {
+            return if sign == Sign::Positive {fixint_max} else {fixint_min}
+        }
+        // If 0 <= exponent < significand_bits, right shift to get the result.
+        // Otherwise, shift left.
+        // (sign - 1) will never overflow as negative signs are already returned as 0 for unsigned
+        let r = if exponent < significand_bits {
+            (significand >> (significand_bits - exponent)) as $ity
+        } else {
+            (significand as $ity) << (exponent - significand_bits)
+        };
 
-            if sign == Sign::Negative {
-                (!r).wrapping_add(1)
-            } else {
-                r
-            }
+        if sign == Sign::Negative {
+            (!r).wrapping_add(1)
+        } else {
+            r
         }
-    }
+    })
 }
 
-macro_rules! float_to_int_unadj_on_win {
-    ($intrinsic:ident: $fty:ty, $ity:ty) => {
-        #[cfg(all(windows, target_pointer_width="64"))]
-        float_to_int!($intrinsic: $fty, $ity, "unadjusted");
-        #[cfg(not(all(windows, target_pointer_width="64")))]
-        float_to_int!($intrinsic: $fty, $ity, "C");
-    };
-}
+intrinsics! {
+    pub extern "C" fn __fixsfsi(f: f32) -> i32 {
+        float_to_int!(f, f32, i32)
+    }
+
+    pub extern "C" fn __fixsfdi(f: f32) -> i64 {
+        float_to_int!(f, f32, i64)
+    }
+
+    #[unadjusted_on_win64]
+    pub extern "C" fn __fixsfti(f: f32) -> i128 {
+        float_to_int!(f, f32, i128)
+    }
+
+    pub extern "C" fn __fixdfsi(f: f64) -> i32 {
+        float_to_int!(f, f64, i32)
+    }
+
+    pub extern "C" fn __fixdfdi(f: f64) -> i64 {
+        float_to_int!(f, f64, i64)
+    }
 
-float_to_int!(__fixsfsi: f32, i32);
-float_to_int!(__fixsfdi: f32, i64);
-float_to_int_unadj_on_win!(__fixsfti: f32, i128);
-float_to_int!(__fixdfsi: f64, i32);
-float_to_int!(__fixdfdi: f64, i64);
-float_to_int_unadj_on_win!(__fixdfti: f64, i128);
-
-float_to_int!(__fixunssfsi: f32, u32);
-float_to_int!(__fixunssfdi: f32, u64);
-float_to_int_unadj_on_win!(__fixunssfti: f32, u128);
-float_to_int!(__fixunsdfsi: f64, u32);
-float_to_int!(__fixunsdfdi: f64, u64);
-float_to_int_unadj_on_win!(__fixunsdfti: f64, u128);
+    #[unadjusted_on_win64]
+    pub extern "C" fn __fixdfti(f: f64) -> i128 {
+        float_to_int!(f, f64, i128)
+    }
+
+    pub extern "C" fn __fixunssfsi(f: f32) -> u32 {
+        float_to_int!(f, f32, u32)
+    }
+
+    pub extern "C" fn __fixunssfdi(f: f32) -> u64 {
+        float_to_int!(f, f32, u64)
+    }
+
+    #[unadjusted_on_win64]
+    pub extern "C" fn __fixunssfti(f: f32) -> u128 {
+        float_to_int!(f, f32, u128)
+    }
+
+    pub extern "C" fn __fixunsdfsi(f: f64) -> u32 {
+        float_to_int!(f, f64, u32)
+    }
+
+    pub extern "C" fn __fixunsdfdi(f: f64) -> u64 {
+        float_to_int!(f, f64, u64)
+    }
+
+    #[unadjusted_on_win64]
+    pub extern "C" fn __fixunsdfti(f: f64) -> u128 {
+        float_to_int!(f, f64, u128)
+    }
+}

+ 28 - 24
src/float/pow.rs

@@ -1,30 +1,34 @@
+/// Returns `a` raised to the power `b`
 macro_rules! pow {
-    ($intrinsic:ident: $fty:ty, $ity:ident) => {
-        /// Returns `a` raised to the power `b`
-        #[cfg_attr(not(test), no_mangle)]
-        pub extern "C" fn $intrinsic(a: $fty, b: $ity) -> $fty {
-            let (mut a, mut b) = (a, b);
-            let recip = b < 0;
-            let mut r: $fty = 1.0;
-            loop {
-                if (b & 1) != 0 {
-                    r *= a;
-                }
-                b = sdiv!($ity, b, 2);
-                if b == 0 {
-                    break;
-                }
-                a *= a;
+    ($a: expr, $b: expr) => ({
+        let (mut a, mut b) = ($a, $b);
+        let recip = b < 0;
+        let mut r = 1.0;
+        loop {
+            if (b & 1) != 0 {
+                r *= a;
             }
-
-            if recip {
-                1.0 / r
-            } else {
-                r
+            b = b.checked_div(2).unwrap_or_else(|| ::abort());
+            if b == 0 {
+                break;
             }
+            a *= a;
         }
-    }
+
+        if recip {
+            1.0 / r
+        } else {
+            r
+        }
+    })
 }
 
-pow!(__powisf2: f32, i32);
-pow!(__powidf2: f64, i32);
+intrinsics! {
+    pub extern "C" fn __powisf2(a: f32, b: i32) -> f32 {
+        pow!(a, b)
+    }
+
+    pub extern "C" fn __powidf2(a: f64, b: i32) -> f64 {
+        pow!(a, b)
+    }
+}

+ 7 - 16
src/float/sub.rs

@@ -1,20 +1,11 @@
 use float::Float;
 
-macro_rules! sub {
-    ($(#[$attr:meta])*
-     | $intrinsic:ident: $ty:ty) => {
-        /// Returns `a - b`
-        $(#[$attr])*
-        pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $ty {
-            a + <$ty>::from_repr(b.repr() ^ <$ty>::sign_mask())
-        }
+intrinsics! {
+    pub extern "C" fn __subsf3(a: f32, b: f32) -> f32 {
+        a + f32::from_repr(b.repr() ^ f32::sign_mask())
     }
-}
-
-sub!(#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)]
-     #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))]
-     | __subsf3: f32);
 
-sub!(#[cfg_attr(all(not(test), not(target_arch = "arm")), no_mangle)]
-     #[cfg_attr(all(not(test), target_arch = "arm"), inline(always))]
-     | __subdf3: f64);
+    pub extern "C" fn __subdf3(a: f64, b: f64) -> f64 {
+        a + f64::from_repr(b.repr() ^ f64::sign_mask())
+    }
+}

+ 10 - 12
src/int/udiv.rs

@@ -1,5 +1,3 @@
-use core::intrinsics;
-
 use int::{Int, LargeInt};
 
 macro_rules! udivmod_inner {
@@ -13,9 +11,11 @@ macro_rules! udivmod_inner {
                 // 0 X
 
                 if let Some(rem) = rem {
-                    *rem = <$ty>::from(urem!(n.low(), d.low()));
+                    *rem = <$ty>::from(n.low().checked_rem(d.low())
+                                        .unwrap_or_else(|| ::abort()));
                 }
-                return <$ty>::from(udiv!(n.low(), d.low()));
+                return <$ty>::from(n.low().checked_div(d.low())
+                                    .unwrap_or_else(|| ::abort()));
             } else {
                 // 0 X
                 // ---
@@ -38,9 +38,7 @@ macro_rules! udivmod_inner {
                 // 0 0
                 // NOTE This should be unreachable in safe Rust because the program will panic before
                 // this intrinsic is called
-                unsafe {
-                    intrinsics::abort()
-                }
+                ::abort();
             }
 
             if n.low() == 0 {
@@ -48,9 +46,11 @@ macro_rules! udivmod_inner {
                 // ---
                 // K 0
                 if let Some(rem) = rem {
-                    *rem = <$ty>::from_parts(0, urem!(n.high(), d.high()));
+                    *rem = <$ty>::from_parts(0, n.high().checked_rem(d.high())
+                                                 .unwrap_or_else(|| ::abort()));
                 }
-                return <$ty>::from(udiv!(n.high(), d.high()));
+                return <$ty>::from(n.high().checked_div(d.high())
+                                    .unwrap_or_else(|| ::abort()));
             }
 
             // K K
@@ -161,9 +161,7 @@ intrinsics! {
         if d == 0 {
             // NOTE This should be unreachable in safe Rust because the program will panic before
             // this intrinsic is called
-            unsafe {
-                intrinsics::abort()
-            }
+            ::abort();
         }
 
         if n == 0 {

+ 0 - 46
src/lib.rs

@@ -32,52 +32,6 @@
 // that follow "x86 naming convention" (e.g. addsf3). Those aeabi intrinsics must adhere to the
 // AAPCS calling convention (`extern "aapcs"`) because that's how LLVM will call them.
 
-// TODO(rust-lang/rust#37029) use e.g. checked_div(_).unwrap_or_else(|| abort())
-macro_rules! udiv {
-    ($a:expr, $b:expr) => {
-        unsafe {
-            let a = $a;
-            let b = $b;
-
-            if b == 0 {
-                ::core::intrinsics::abort()
-            } else {
-                ::core::intrinsics::unchecked_div(a, b)
-            }
-        }
-    }
-}
-
-macro_rules! sdiv {
-    ($sty:ident, $a:expr, $b:expr) => {
-        unsafe {
-            let a = $a;
-            let b = $b;
-
-            if b == 0 || (b == -1 && a == $sty::min_value()) {
-                ::core::intrinsics::abort()
-            } else {
-                ::core::intrinsics::unchecked_div(a, b)
-            }
-        }
-    }
-}
-
-macro_rules! urem {
-    ($a:expr, $b:expr) => {
-        unsafe {
-            let a = $a;
-            let b = $b;
-
-            if b == 0 {
-                ::core::intrinsics::abort()
-            } else {
-                ::core::intrinsics::unchecked_rem(a, b)
-            }
-        }
-    }
-}
-
 #[cfg(test)]
 extern crate core;