Skip to content

Commit dc91c0e

Browse files
committed
i128 mul intrinsics
1 parent 84ba770 commit dc91c0e

File tree

5 files changed

+44
-15
lines changed

5 files changed

+44
-15
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,8 +206,8 @@ These builtins are needed to support 128-bit integers, which are in the process
206206
- [ ] floatuntisf.c
207207
- [ ] lshrti3.c
208208
- [ ] modti3.c
209-
- [ ] muloti4.c
210-
- [ ] multi3.c
209+
- [x] muloti4.c
210+
- [x] multi3.c
211211
- [ ] udivmodti4.c
212212
- [ ] udivti3.c
213213
- [ ] umodti3.c

build.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ fn main() {
150150
"int_util.c",
151151
"muldc3.c",
152152
"muldf3.c",
153-
"muloti4.c",
154153
"mulsc3.c",
155154
"mulsf3.c",
156155
"mulvdi3.c",
@@ -202,7 +201,6 @@ fn main() {
202201
"lshrti3.c",
203202
"modti3.c",
204203
"multf3.c",
205-
"multi3.c",
206204
"mulvti3.c",
207205
"negti2.c",
208206
"negvti2.c",

src/int/mod.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,13 @@ large_int!(i64, u32, i32, 32);
6565
large_int!(u128, u64, u64, 64);
6666
#[cfg(not(stage0))]
6767
large_int!(i128, u64, i64, 64);
68+
69+
// Hack for LLVM expectations for ABI on windows
70+
#[cfg(all(windows, target_pointer_width="64"))]
71+
#[repr(simd)]
72+
pub struct U64x2(u64, u64);
73+
74+
#[cfg(all(windows, target_pointer_width="64"))]
75+
fn conv(i: u128) -> U64x2 {
76+
U64x2(i.low(), i.high())
77+
}

src/int/mul.rs

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
#[cfg(not(all(feature = "c", target_arch = "x86")))]
21
use int::LargeInt;
32
use int::Int;
43

54
macro_rules! mul {
6-
($intrinsic:ident: $ty:ty) => {
5+
($intrinsic:ident: $ty:ty, $tyh:ty) => {
76
/// Returns `a * b`
87
#[cfg_attr(not(test), no_mangle)]
98
pub extern "C" fn $intrinsic(a: $ty, b: $ty) -> $ty {
@@ -14,31 +13,36 @@ macro_rules! mul {
1413
low &= lower_mask;
1514
t += (a.low() >> half_bits).wrapping_mul(b.low() & lower_mask);
1615
low += (t & lower_mask) << half_bits;
17-
let mut high = t >> half_bits;
16+
let mut high = (t >> half_bits) as $tyh;
1817
t = low >> half_bits;
1918
low &= lower_mask;
2019
t += (b.low() >> half_bits).wrapping_mul(a.low() & lower_mask);
2120
low += (t & lower_mask) << half_bits;
22-
high += t >> half_bits;
23-
high += (a.low() >> half_bits).wrapping_mul(b.low() >> half_bits);
24-
high = high.wrapping_add(a.high().wrapping_mul(b.low()).wrapping_add(a.low().wrapping_mul(b.high())));
21+
high += (t >> half_bits) as $tyh;
22+
high += (a.low() >> half_bits).wrapping_mul(b.low() >> half_bits) as $tyh;
23+
high = high.wrapping_add(a.high().wrapping_mul(b.low() as $tyh))
24+
.wrapping_add((a.low() as $tyh).wrapping_mul(b.high()));
2525
<$ty>::from_parts(low, high)
2626
}
2727
}
2828
}
2929

3030
macro_rules! mulo {
3131
($intrinsic:ident: $ty:ty) => {
32+
// Default is "C" ABI
33+
mulo!($intrinsic: $ty, "C", |i| { i }, $ty);
34+
};
35+
($intrinsic:ident: $ty:ty, $abi:tt, $conv:expr, $rty:ty) => {
3236
/// Returns `a * b` and sets `*overflow = 1` if `a * b` overflows
3337
#[cfg_attr(not(test), no_mangle)]
34-
pub extern "C" fn $intrinsic(a: $ty, b: $ty, overflow: &mut i32) -> $ty {
38+
pub extern $abi fn $intrinsic(a: $ty, b: $ty, overflow: &mut i32) -> $rty {
3539
*overflow = 0;
3640
let result = a.wrapping_mul(b);
3741
if a == <$ty>::min_value() {
3842
if b != 0 && b != 1 {
3943
*overflow = 1;
4044
}
41-
return result;
45+
return ($conv)(result);
4246
}
4347
if b == <$ty>::min_value() {
4448
if a != 0 && a != 1 {
@@ -52,7 +56,7 @@ macro_rules! mulo {
5256
let sb = b >> (<$ty>::bits() - 1);
5357
let abs_b = (b ^ sb) - sb;
5458
if abs_a < 2 || abs_b < 2 {
55-
return result;
59+
return ($conv)(result);
5660
}
5761
if sa == sb {
5862
if abs_a > <$ty>::max_value() / abs_b {
@@ -63,17 +67,31 @@ macro_rules! mulo {
6367
*overflow = 1;
6468
}
6569
}
66-
result
70+
($conv)(result)
6771
}
6872
}
6973
}
7074

7175
#[cfg(not(all(feature = "c", target_arch = "x86")))]
72-
mul!(__muldi3: u64);
76+
mul!(__muldi3: u64, u32);
77+
78+
#[cfg(stage0)]
79+
mul!(__multi3: u64, u32);
80+
#[cfg(not(stage0))]
81+
mul!(__multi3: i128, i64);
7382

7483
mulo!(__mulosi4: i32);
7584
mulo!(__mulodi4: i64);
7685

86+
#[cfg(stage0)]
87+
mulo!(__muloti4: i64);
88+
#[cfg(not(stage0))]
89+
#[cfg(all(windows, target_pointer_width="64"))]
90+
mulo!(__muloti4: i128, "unadjusted", super::conv, super::U64x2);
91+
#[cfg(not(stage0))]
92+
#[cfg(not(all(windows, target_pointer_width="64")))]
93+
mulo!(__muloti4: i128);
94+
7795
#[cfg(test)]
7896
mod tests {
7997
use qc::{I32, I64, U64};

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#![feature(naked_functions)]
1515
#![feature(staged_api)]
1616
#![feature(i128_type)]
17+
#![feature(repr_simd)]
18+
#![feature(abi_unadjusted)]
19+
#![allow(unused_features)]
1720
#![no_builtins]
1821
#![unstable(feature = "compiler_builtins_lib",
1922
reason = "Compiler builtins. Will never become stable.",

0 commit comments

Comments
 (0)