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)]
|
// TODO use `global_asm!`
|
||||||
pub struct u64x2 {
|
#[naked]
|
||||||
a: u64,
|
#[no_mangle]
|
||||||
b: u64,
|
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]
|
#[no_mangle]
|
||||||
pub unsafe extern "aapcs" fn __aeabi_uldivmod(num: u64, den: u64) -> u64x2 {
|
pub unsafe extern "aapcs" fn __aeabi_uldivmod() {
|
||||||
|
asm!("push {r11, lr}
|
||||||
let mut rem = mem::uninitialized();
|
sub sp, sp, #16
|
||||||
let quot = ::__udivmoddi4(num, den, &mut rem);
|
add r12, sp, #8
|
||||||
|
str r12, [sp]
|
||||||
u64x2 { a: quot, b: rem }
|
bl __udivmoddi4
|
||||||
|
ldr r2, [sp, #8]
|
||||||
|
ldr r3, [sp, #12]
|
||||||
|
add sp, sp, #16
|
||||||
|
pop {r11, pc}");
|
||||||
|
intrinsics::unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
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()
|
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