replace old soft division code with new functions
This commit is contained in:
parent
981e803acd
commit
3fda53a90d
2 changed files with 33 additions and 76 deletions
|
|
@ -57,54 +57,59 @@ trait Divmod: Int {
|
|||
impl Divmod for i32 {}
|
||||
impl Divmod for i64 {}
|
||||
|
||||
|
||||
intrinsics! {
|
||||
#[maybe_use_optimized_c_shim]
|
||||
#[arm_aeabi_alias = __aeabi_idiv]
|
||||
/// Returns `n / d`
|
||||
pub extern "C" fn __divsi3(a: i32, b: i32) -> i32 {
|
||||
a.div(b)
|
||||
i32_div_rem(a, b).0
|
||||
}
|
||||
|
||||
#[maybe_use_optimized_c_shim]
|
||||
/// Returns `n % d`
|
||||
pub extern "C" fn __modsi3(a: i32, b: i32) -> i32 {
|
||||
a.mod_(b)
|
||||
i32_div_rem(a, b).1
|
||||
}
|
||||
|
||||
|
||||
#[maybe_use_optimized_c_shim]
|
||||
/// Returns `n / d` and sets `*rem = n % d`
|
||||
pub extern "C" fn __divmodsi4(a: i32, b: i32, rem: &mut i32) -> i32 {
|
||||
a.divmod(b, rem, |a, b| __divsi3(a, b))
|
||||
let quo_rem = i32_div_rem(a, b);
|
||||
*rem = quo_rem.1;
|
||||
quo_rem.0
|
||||
}
|
||||
|
||||
#[maybe_use_optimized_c_shim]
|
||||
/// Returns `n / d`
|
||||
pub extern "C" fn __divdi3(a: i64, b: i64) -> i64 {
|
||||
a.div(b)
|
||||
i64_div_rem(a, b).0
|
||||
}
|
||||
|
||||
#[maybe_use_optimized_c_shim]
|
||||
/// Returns `n % d`
|
||||
pub extern "C" fn __moddi3(a: i64, b: i64) -> i64 {
|
||||
a.mod_(b)
|
||||
i64_div_rem(a, b).1
|
||||
}
|
||||
|
||||
#[aapcs_on_arm]
|
||||
/// Returns `n / d` and sets `*rem = n % d`
|
||||
pub extern "C" fn __divmoddi4(a: i64, b: i64, rem: &mut i64) -> i64 {
|
||||
a.divmod(b, rem, |a, b| __divdi3(a, b))
|
||||
let quo_rem = i64_div_rem(a, b);
|
||||
*rem = quo_rem.1;
|
||||
quo_rem.0
|
||||
}
|
||||
|
||||
#[win64_128bit_abi_hack]
|
||||
/// Returns `n / d`
|
||||
pub extern "C" fn __divti3(a: i128, b: i128) -> i128 {
|
||||
a.div(b)
|
||||
i128_div_rem(a, b).0
|
||||
}
|
||||
|
||||
#[win64_128bit_abi_hack]
|
||||
/// Returns `n % d`
|
||||
pub extern "C" fn __modti3(a: i128, b: i128) -> i128 {
|
||||
a.mod_(b)
|
||||
i128_div_rem(a, b).1
|
||||
}
|
||||
|
||||
// LLVM does not currently have a `__divmodti4` function
|
||||
|
|
|
|||
|
|
@ -156,113 +156,65 @@ intrinsics! {
|
|||
#[arm_aeabi_alias = __aeabi_uidiv]
|
||||
/// Returns `n / d`
|
||||
pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 {
|
||||
// Special cases
|
||||
if d == 0 {
|
||||
// NOTE This should be unreachable in safe Rust because the program will panic before
|
||||
// this intrinsic is called
|
||||
::abort();
|
||||
}
|
||||
|
||||
if n == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut sr = d.leading_zeros().wrapping_sub(n.leading_zeros());
|
||||
|
||||
// d > n
|
||||
if sr > u32::BITS - 1 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// d == 1
|
||||
if sr == u32::BITS - 1 {
|
||||
return n;
|
||||
}
|
||||
|
||||
sr += 1;
|
||||
|
||||
// 1 <= sr <= u32::BITS - 1
|
||||
let mut q = n << (u32::BITS - sr);
|
||||
let mut r = n >> sr;
|
||||
|
||||
let mut carry = 0;
|
||||
|
||||
// Don't use a range because they may generate references to memcpy in unoptimized code
|
||||
let mut i = 0;
|
||||
while i < sr {
|
||||
i += 1;
|
||||
|
||||
// r:q = ((r:q) << 1) | carry
|
||||
r = (r << 1) | (q >> (u32::BITS - 1));
|
||||
q = (q << 1) | carry;
|
||||
|
||||
// carry = 0;
|
||||
// if r > d {
|
||||
// r -= d;
|
||||
// carry = 1;
|
||||
// }
|
||||
|
||||
let s = (d.wrapping_sub(r).wrapping_sub(1)) as i32 >> (u32::BITS - 1);
|
||||
carry = (s & 1) as u32;
|
||||
r -= d & s as u32;
|
||||
}
|
||||
|
||||
(q << 1) | carry
|
||||
u32_div_rem(n, d).0
|
||||
}
|
||||
|
||||
#[maybe_use_optimized_c_shim]
|
||||
/// Returns `n % d`
|
||||
pub extern "C" fn __umodsi3(n: u32, d: u32) -> u32 {
|
||||
let q = __udivsi3(n, d);
|
||||
n - q * d
|
||||
u32_div_rem(n, d).1
|
||||
}
|
||||
|
||||
#[maybe_use_optimized_c_shim]
|
||||
/// Returns `n / d` and sets `*rem = n % d`
|
||||
pub extern "C" fn __udivmodsi4(n: u32, d: u32, rem: Option<&mut u32>) -> u32 {
|
||||
let q = __udivsi3(n, d);
|
||||
let quo_rem = u32_div_rem(n, d);
|
||||
if let Some(rem) = rem {
|
||||
*rem = n - (q * d);
|
||||
*rem = quo_rem.1;
|
||||
}
|
||||
q
|
||||
quo_rem.0
|
||||
}
|
||||
|
||||
#[maybe_use_optimized_c_shim]
|
||||
/// Returns `n / d`
|
||||
pub extern "C" fn __udivdi3(n: u64, d: u64) -> u64 {
|
||||
__udivmoddi4(n, d, None)
|
||||
u64_div_rem(n, d).0
|
||||
}
|
||||
|
||||
#[maybe_use_optimized_c_shim]
|
||||
/// Returns `n % d`
|
||||
pub extern "C" fn __umoddi3(n: u64, d: u64) -> u64 {
|
||||
let mut rem = 0;
|
||||
__udivmoddi4(n, d, Some(&mut rem));
|
||||
rem
|
||||
u64_div_rem(n, d).1
|
||||
}
|
||||
|
||||
/// Returns `n / d` and sets `*rem = n % d`
|
||||
pub extern "C" fn __udivmoddi4(n: u64, d: u64, rem: Option<&mut u64>) -> u64 {
|
||||
udivmod_inner!(n, d, rem, u64)
|
||||
let quo_rem = u64_div_rem(n, d);
|
||||
if let Some(rem) = rem {
|
||||
*rem = quo_rem.1;
|
||||
}
|
||||
quo_rem.0
|
||||
}
|
||||
|
||||
#[win64_128bit_abi_hack]
|
||||
/// Returns `n / d`
|
||||
pub extern "C" fn __udivti3(n: u128, d: u128) -> u128 {
|
||||
__udivmodti4(n, d, None)
|
||||
u128_div_rem(n, d).0
|
||||
}
|
||||
|
||||
#[win64_128bit_abi_hack]
|
||||
/// Returns `n % d`
|
||||
pub extern "C" fn __umodti3(n: u128, d: u128) -> u128 {
|
||||
let mut rem = 0;
|
||||
__udivmodti4(n, d, Some(&mut rem));
|
||||
rem
|
||||
u128_div_rem(n, d).1
|
||||
}
|
||||
|
||||
#[win64_128bit_abi_hack]
|
||||
/// Returns `n / d` and sets `*rem = n % d`
|
||||
pub extern "C" fn __udivmodti4(n: u128, d: u128, rem: Option<&mut u128>) -> u128 {
|
||||
udivmod_inner!(n, d, rem, u128)
|
||||
let quo_rem = u128_div_rem(n, d);
|
||||
if let Some(rem) = rem {
|
||||
*rem = quo_rem.1;
|
||||
}
|
||||
quo_rem.0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue