port __udivmodsi4, aeabi_uidivmod and udivsi3
also rewrite these last two new aeabi intrinsics as naked functions
This commit is contained in:
parent
39ede7ee27
commit
cc9d3e8e5f
37
src/arm.rs
37
src/arm.rs
|
@ -1,18 +1,33 @@
|
|||
use core::mem;
|
||||
use core::intrinsics;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct u64x2 {
|
||||
a: u64,
|
||||
b: u64,
|
||||
// TODO use `global_asm!`
|
||||
#[naked]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "aapcs" fn __aeabi_uidivmod() {
|
||||
asm!("push { lr }
|
||||
sub sp, sp, #4
|
||||
mov r2, sp
|
||||
bl __udivmodsi4
|
||||
ldr r1, [sp]
|
||||
add sp, sp, #4
|
||||
pop { pc }");
|
||||
intrinsics::unreachable();
|
||||
}
|
||||
|
||||
// TODO use `global_asm!`
|
||||
#[naked]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "aapcs" fn __aeabi_uldivmod(num: u64, den: u64) -> u64x2 {
|
||||
|
||||
let mut rem = mem::uninitialized();
|
||||
let quot = ::__udivmoddi4(num, den, &mut rem);
|
||||
|
||||
u64x2 { a: quot, b: rem }
|
||||
pub unsafe extern "aapcs" fn __aeabi_uldivmod() {
|
||||
asm!("push {r11, lr}
|
||||
sub sp, sp, #16
|
||||
add r12, sp, #8
|
||||
str r12, [sp]
|
||||
bl __udivmoddi4
|
||||
ldr r2, [sp, #8]
|
||||
ldr r3, [sp, #12]
|
||||
add sp, sp, #16
|
||||
pop {r11, pc}");
|
||||
intrinsics::unreachable();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
|
61
src/lib.rs
61
src/lib.rs
|
@ -352,3 +352,64 @@ pub extern "C" fn __udivmoddi4(a: u64, b: u64, rem: *mut u64) -> u64 {
|
|||
}
|
||||
q.u64()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __udivmodsi4(a: u32, b: u32, rem: *mut u32) -> u32 {
|
||||
let d = __udivsi3(a, b);
|
||||
if let Some(rem) = unsafe {rem.as_mut()} {
|
||||
*rem = a - (d*b);
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 {
|
||||
let u32_bits = u32::bits() as u32;
|
||||
|
||||
// Special cases
|
||||
if d == 0 {
|
||||
return 0; // ?!
|
||||
}
|
||||
|
||||
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 = sr + 1;
|
||||
|
||||
// 1 <= sr <= u32_bits - 1
|
||||
let mut q = n << (u32_bits - sr);
|
||||
let mut r = n >> sr;
|
||||
|
||||
let mut carry = 0;
|
||||
for _ in 0..sr {
|
||||
// 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 = (q << 1) | carry;
|
||||
q
|
||||
}
|
||||
|
|
13
src/test.rs
13
src/test.rs
|
@ -42,3 +42,16 @@ quickcheck! {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
quickcheck! {
|
||||
fn udivmodsi4(a: u32, b: u32) -> TestResult {
|
||||
if b == 0 {
|
||||
TestResult::discard()
|
||||
} else {
|
||||
let mut r = 0;
|
||||
let q = ::__udivmodsi4(a, b, &mut r);
|
||||
|
||||
TestResult::from_bool(q * b + r == a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue