i128 mul intrinsics

This commit is contained in:
est31 2017-01-04 02:42:03 +01:00
parent b356429374
commit 3055aa21b6
4 changed files with 24 additions and 12 deletions

View File

@ -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

View File

@ -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",

View File

@ -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};

View File

@ -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.",