Skip to content

Commit d2eae2e

Browse files
committed
u128 udiv intrinsics
1 parent d053642 commit d2eae2e

File tree

4 files changed

+75
-20
lines changed

4 files changed

+75
-20
lines changed

Diff for: README.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,9 @@ These builtins are needed to support 128-bit integers, which are in the process
208208
- [ ] modti3.c
209209
- [x] muloti4.c
210210
- [x] multi3.c
211-
- [ ] udivmodti4.c
212-
- [ ] udivti3.c
213-
- [ ] umodti3.c
211+
- [x] udivmodti4.c
212+
- [x] udivti3.c
213+
- [x] umodti3.c
214214

215215
## Unimplemented functions
216216

Diff for: build.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -207,10 +207,7 @@ fn main() {
207207
"subtf3.c",
208208
"subvti3.c",
209209
"trampoline_setup.c",
210-
"ucmpti2.c",
211-
"udivmodti4.c",
212-
"udivti3.c",
213-
"umodti3.c"]);
210+
"ucmpti2.c"]);
214211
}
215212

216213
if target_vendor == "apple" {

Diff for: src/int/udiv.rs

+60-13
Original file line numberDiff line numberDiff line change
@@ -96,23 +96,45 @@ pub extern "C" fn __udivmodsi4(n: u32, d: u32, rem: Option<&mut u32>) -> u32 {
9696
q
9797
}
9898

99-
/// Returns `n / d`
100-
#[cfg_attr(not(test), no_mangle)]
101-
#[cfg(not(all(feature = "c", target_arch = "x86")))]
102-
pub extern "C" fn __udivdi3(n: u64, d: u64) -> u64 {
103-
__udivmoddi4(n, d, None)
99+
macro_rules! div_mod_intrinsics {
100+
($udiv_intr:ident, $umod_intr:ident : $ty:ty) => {
101+
div_mod_intrinsics!($udiv_intr, $umod_intr : $ty,
102+
__udivmoddi4);
103+
};
104+
($udiv_intr:ident, $umod_intr:ident : $ty:ty, $divmod_intr:expr) => {
105+
div_mod_intrinsics!($udiv_intr, $umod_intr : $ty,
106+
$divmod_intr, $ty, |i|{ i });
107+
};
108+
($udiv_intr:ident, $umod_intr:ident : $ty:ty, $divmod_intr:expr,
109+
$tyret:ty, $conv:expr) => {
110+
/// Returns `n / d`
111+
pub extern "C" fn $udiv_intr(n: $ty, d: $ty) -> $tyret {
112+
let r = $divmod_intr(n, d, None);
113+
($conv)(r)
114+
}
115+
116+
/// Returns `n % d`
117+
pub extern "C" fn $umod_intr(a: $ty, b: $ty) -> $tyret {
118+
use core::mem;
119+
120+
let mut rem = unsafe { mem::uninitialized() };
121+
$divmod_intr(a, b, Some(&mut rem));
122+
($conv)(rem)
123+
}
124+
}
104125
}
105126

106-
/// Returns `n % d`
107-
#[cfg(not(all(feature = "c", target_arch = "x86")))]
108127
#[cfg_attr(not(test), no_mangle)]
109-
pub extern "C" fn __umoddi3(a: u64, b: u64) -> u64 {
110-
use core::mem;
128+
#[cfg(not(all(feature = "c", target_arch = "x86")))]
129+
div_mod_intrinsics!(__udivdi3, __umoddi3: u64);
111130

112-
let mut rem = unsafe { mem::uninitialized() };
113-
__udivmoddi4(a, b, Some(&mut rem));
114-
rem
115-
}
131+
#[cfg(not(stage0))]
132+
#[cfg(not(all(windows, target_pointer_width="64")))]
133+
div_mod_intrinsics!(__udivti3, __umodti3: u128, u128_div_mod);
134+
135+
#[cfg(not(stage0))]
136+
#[cfg(all(windows, target_pointer_width="64"))]
137+
div_mod_intrinsics!(__udivti3, __umodti3: u128, u128_div_mod, ::U64x2, ::conv);
116138

117139
macro_rules! udivmod_inner {
118140
($n:expr, $d:expr, $rem:expr, $ty:ty) => {{
@@ -269,6 +291,31 @@ pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
269291
udivmod_inner!(n, d, rem, u64)
270292
}
271293

294+
macro_rules! udivmodti4 {
295+
($tyret:ty, $conv:expr) => {
296+
/// Returns `n / d` and sets `*rem = n % d`
297+
#[cfg_attr(not(test), no_mangle)]
298+
pub extern "C" fn __udivmodti4(n: u128, d: u128, rem: Option<&mut u128>) -> $tyret {
299+
let r = u128_div_mod(n, d, rem);
300+
($conv)(r)
301+
}
302+
}
303+
}
304+
305+
/// Returns `n / d` and sets `*rem = n % d`
306+
#[cfg(not(stage0))]
307+
fn u128_div_mod(n: u128, d: u128, rem: Option<&mut u128>) -> u128 {
308+
udivmod_inner!(n, d, rem, u128)
309+
}
310+
311+
#[cfg(not(stage0))]
312+
#[cfg(all(windows, target_pointer_width="64"))]
313+
udivmodti4!(::U64x2, ::conv);
314+
315+
#[cfg(not(stage0))]
316+
#[cfg(not(all(windows, target_pointer_width="64")))]
317+
udivmodti4!(u128, |i|{ i });
318+
272319
#[cfg(test)]
273320
mod tests {
274321
use qc::{U32, U64};

Diff for: src/lib.rs

+11
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,17 @@ type U128_ = u128;
100100
#[cfg(not(stage0))]
101101
type I128_ = i128;
102102

103+
// Hack for LLVM expectations for ABI on windows
104+
#[cfg(all(windows, target_pointer_width="64"))]
105+
#[repr(simd)]
106+
struct U64x2(u64, u64);
107+
108+
#[cfg(all(windows, target_pointer_width="64"))]
109+
fn conv(i: u128) -> U64x2 {
110+
use int::LargeInt;
111+
U64x2(i.low(), i.high())
112+
}
113+
103114
#[cfg(test)]
104115
#[macro_use]
105116
extern crate quickcheck;

0 commit comments

Comments
 (0)