diff --git a/README.md b/README.md index d66d888..8e81dde 100644 --- a/README.md +++ b/README.md @@ -206,8 +206,8 @@ These builtins are needed to support 128-bit integers, which are in the process - [ ] floatuntisf.c - [ ] lshrti3.c - [ ] modti3.c -- [ ] muloti4.c -- [ ] multi3.c +- [x] muloti4.c +- [x] multi3.c - [ ] udivmodti4.c - [ ] udivti3.c - [ ] umodti3.c diff --git a/build.rs b/build.rs index e6ad4c6..0ecb0d0 100644 --- a/build.rs +++ b/build.rs @@ -150,7 +150,6 @@ fn main() { "int_util.c", "muldc3.c", "muldf3.c", - "muloti4.c", "mulsc3.c", "mulsf3.c", "mulvdi3.c", @@ -202,7 +201,6 @@ fn main() { "lshrti3.c", "modti3.c", "multf3.c", - "multi3.c", "mulvti3.c", "negti2.c", "negvti2.c", diff --git a/src/int/mul.rs b/src/int/mul.rs index 0403aa9..d46bc90 100644 --- a/src/int/mul.rs +++ b/src/int/mul.rs @@ -1,9 +1,8 @@ -#[cfg(not(all(feature = "c", target_arch = "x86")))] use int::LargeInt; use int::Int; macro_rules! mul { - ($intrinsic:ident: $ty:ty) => { + ($intrinsic:ident: $ty:ty, $tyh:ty) => { /// Returns `a * b` #[cfg_attr(not(test), no_mangle)] pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $ty { @@ -14,14 +13,15 @@ macro_rules! mul { low &= lower_mask; t += (a.low() >> half_bits).wrapping_mul(b.low() & lower_mask); low += (t & lower_mask) << half_bits; - let mut high = t >> half_bits; + let mut high = (t >> half_bits) as $tyh; t = low >> half_bits; low &= lower_mask; t += (b.low() >> half_bits).wrapping_mul(a.low() & lower_mask); low += (t & lower_mask) << half_bits; - high += t >> half_bits; - high += (a.low() >> half_bits).wrapping_mul(b.low() >> half_bits); - high = high.wrapping_add(a.high().wrapping_mul(b.low()).wrapping_add(a.low().wrapping_mul(b.high()))); + high += (t >> half_bits) as $tyh; + high += (a.low() >> half_bits).wrapping_mul(b.low() >> half_bits) as $tyh; + high = high.wrapping_add(a.high().wrapping_mul(b.low() as $tyh)) + .wrapping_add((a.low() as $tyh).wrapping_mul(b.high())); <$ty>::from_parts(low, high) } } @@ -29,9 +29,13 @@ macro_rules! mul { macro_rules! mulo { ($intrinsic:ident: $ty:ty) => { + // Default is "C" ABI + mulo!($intrinsic: $ty, "C"); + }; + ($intrinsic:ident: $ty:ty, $abi:tt) => { /// Returns `a * b` and sets `*overflow = 1` if `a * b` overflows #[cfg_attr(not(test), no_mangle)] - pub extern "C" fn $intrinsic(a: $ty, b: $ty, overflow: &mut i32) -> $ty { + pub extern $abi fn $intrinsic(a: $ty, b: $ty, overflow: &mut i32) -> $ty { *overflow = 0; let result = a.wrapping_mul(b); if a == <$ty>::min_value() { @@ -69,11 +73,18 @@ macro_rules! mulo { } #[cfg(not(all(feature = "c", target_arch = "x86")))] -mul!(__muldi3: u64); +mul!(__muldi3: u64, u32); + +mul!(__multi3: i128, i64); mulo!(__mulosi4: i32); mulo!(__mulodi4: i64); +#[cfg(all(windows, target_pointer_width="64"))] +mulo!(__muloti4: i128, "unadjusted"); +#[cfg(not(all(windows, target_pointer_width="64")))] +mulo!(__muloti4: i128); + #[cfg(test)] mod tests { use qc::{I32, I64, U64}; diff --git a/src/lib.rs b/src/lib.rs index 21d7902..f637ff5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,9 @@ #![feature(naked_functions)] #![feature(staged_api)] #![feature(i128_type)] +#![feature(repr_simd)] +#![feature(abi_unadjusted)] +#![allow(unused_features)] #![no_builtins] #![unstable(feature = "compiler_builtins_lib", reason = "Compiler builtins. Will never become stable.",