u128 udiv intrinsics

This commit is contained in:
est31 2017-01-05 15:08:56 +01:00
parent 8fe50d813c
commit 2f3c534cfe
4 changed files with 71 additions and 20 deletions

View File

@ -208,9 +208,9 @@ These builtins are needed to support 128-bit integers, which are in the process
- [ ] modti3.c - [ ] modti3.c
- [x] muloti4.c - [x] muloti4.c
- [x] multi3.c - [x] multi3.c
- [ ] udivmodti4.c - [x] udivmodti4.c
- [ ] udivti3.c - [x] udivti3.c
- [ ] umodti3.c - [x] umodti3.c
## Unimplemented functions ## Unimplemented functions

View File

@ -207,10 +207,7 @@ fn main() {
"subtf3.c", "subtf3.c",
"subvti3.c", "subvti3.c",
"trampoline_setup.c", "trampoline_setup.c",
"ucmpti2.c", "ucmpti2.c"]);
"udivmodti4.c",
"udivti3.c",
"umodti3.c"]);
} }
if target_vendor == "apple" { if target_vendor == "apple" {

View File

@ -96,24 +96,45 @@ pub extern "C" fn __udivmodsi4(n: u32, d: u32, rem: Option<&mut u32>) -> u32 {
q q
} }
/// Returns `n / d` macro_rules! div_mod_intrinsics {
#[cfg_attr(not(test), no_mangle)] ($udiv_intr:ident, $umod_intr:ident : $ty:ty) => {
#[cfg(not(all(feature = "c", target_arch = "x86")))] div_mod_intrinsics!($udiv_intr, $umod_intr : $ty,
pub extern "C" fn __udivdi3(n: u64, d: u64) -> u64 { __udivmoddi4);
__udivmoddi4(n, d, None) };
} ($udiv_intr:ident, $umod_intr:ident : $ty:ty, $divmod_intr:expr) => {
div_mod_intrinsics!($udiv_intr, $umod_intr : $ty,
$divmod_intr, $ty, |i|{ i });
};
($udiv_intr:ident, $umod_intr:ident : $ty:ty, $divmod_intr:expr,
$tyret:ty, $conv:expr) => {
/// Returns `n / d`
#[cfg_attr(not(test), no_mangle)]
pub extern "C" fn $udiv_intr(n: $ty, d: $ty) -> $tyret {
let r = $divmod_intr(n, d, None);
($conv)(r)
}
/// Returns `n % d` /// Returns `n % d`
#[cfg(not(all(feature = "c", target_arch = "x86")))] #[cfg_attr(not(test), no_mangle)]
#[cfg_attr(not(test), no_mangle)] pub extern "C" fn $umod_intr(a: $ty, b: $ty) -> $tyret {
pub extern "C" fn __umoddi3(a: u64, b: u64) -> u64 {
use core::mem; use core::mem;
let mut rem = unsafe { mem::uninitialized() }; let mut rem = unsafe { mem::uninitialized() };
__udivmoddi4(a, b, Some(&mut rem)); $divmod_intr(a, b, Some(&mut rem));
rem ($conv)(rem)
}
}
} }
#[cfg(not(all(feature = "c", target_arch = "x86")))]
div_mod_intrinsics!(__udivdi3, __umoddi3: u64);
#[cfg(not(all(windows, target_pointer_width="64")))]
div_mod_intrinsics!(__udivti3, __umodti3: u128, u128_div_mod);
#[cfg(all(windows, target_pointer_width="64"))]
div_mod_intrinsics!(__udivti3, __umodti3: u128, u128_div_mod, ::U64x2, ::conv);
macro_rules! udivmod_inner { macro_rules! udivmod_inner {
($n:expr, $d:expr, $rem:expr, $ty:ty) => {{ ($n:expr, $d:expr, $rem:expr, $ty:ty) => {{
let (n, d, rem) = ($n, $d, $rem); let (n, d, rem) = ($n, $d, $rem);
@ -269,6 +290,28 @@ pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
udivmod_inner!(n, d, rem, u64) udivmod_inner!(n, d, rem, u64)
} }
macro_rules! udivmodti4 {
($tyret:ty, $conv:expr) => {
/// Returns `n / d` and sets `*rem = n % d`
#[cfg_attr(not(test), no_mangle)]
pub extern "C" fn __udivmodti4(n: u128, d: u128, rem: Option<&mut u128>) -> $tyret {
let r = u128_div_mod(n, d, rem);
($conv)(r)
}
}
}
/// Returns `n / d` and sets `*rem = n % d`
fn u128_div_mod(n: u128, d: u128, rem: Option<&mut u128>) -> u128 {
udivmod_inner!(n, d, rem, u128)
}
#[cfg(all(windows, target_pointer_width="64"))]
udivmodti4!(::U64x2, ::conv);
#[cfg(not(all(windows, target_pointer_width="64")))]
udivmodti4!(u128, |i|{ i });
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use qc::{U32, U64}; use qc::{U32, U64};

View File

@ -89,6 +89,17 @@ macro_rules! srem {
} }
} }
// Hack for LLVM expectations for ABI on windows
#[cfg(all(windows, target_pointer_width="64"))]
#[repr(simd)]
pub struct U64x2(u64, u64);
#[cfg(all(windows, target_pointer_width="64"))]
fn conv(i: u128) -> U64x2 {
use int::LargeInt;
U64x2(i.low(), i.high())
}
#[cfg(test)] #[cfg(test)]
#[cfg_attr(target_arch = "arm", macro_use)] #[cfg_attr(target_arch = "arm", macro_use)]
extern crate quickcheck; extern crate quickcheck;