Skip to content

Commit 86bab8a

Browse files
author
Jorge Aparicio
committed
port __udivmodsi4, aeabi_uidivmod and udivsi3
also rewrite these last two new aeabi intrinsics as naked functions
1 parent 66b626e commit 86bab8a

File tree

3 files changed

+100
-11
lines changed

3 files changed

+100
-11
lines changed

src/arm.rs

+26-11
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,33 @@
1-
use core::mem;
1+
use core::intrinsics;
22

3-
#[repr(C)]
4-
pub struct u64x2 {
5-
a: u64,
6-
b: u64,
3+
// TODO use `global_asm!`
4+
#[naked]
5+
#[no_mangle]
6+
pub unsafe extern "aapcs" fn __aeabi_uidivmod() {
7+
asm!("push { lr }
8+
sub sp, sp, #4
9+
mov r2, sp
10+
bl __udivmodsi4
11+
ldr r1, [sp]
12+
add sp, sp, #4
13+
pop { pc }");
14+
intrinsics::unreachable();
715
}
816

17+
// TODO use `global_asm!`
18+
#[naked]
919
#[no_mangle]
10-
pub unsafe extern "aapcs" fn __aeabi_uldivmod(num: u64, den: u64) -> u64x2 {
11-
12-
let mut rem = mem::uninitialized();
13-
let quot = ::__udivmoddi4(num, den, &mut rem);
14-
15-
u64x2 { a: quot, b: rem }
20+
pub unsafe extern "aapcs" fn __aeabi_uldivmod() {
21+
asm!("push {r11, lr}
22+
sub sp, sp, #16
23+
add r12, sp, #8
24+
str r12, [sp]
25+
bl __udivmoddi4
26+
ldr r2, [sp, #8]
27+
ldr r3, [sp, #12]
28+
add sp, sp, #16
29+
pop {r11, pc}");
30+
intrinsics::unreachable();
1631
}
1732

1833
extern "C" {

src/lib.rs

+61
Original file line numberDiff line numberDiff line change
@@ -295,3 +295,64 @@ pub extern "C" fn __udivmoddi4(a: u64, b: u64, rem: *mut u64) -> u64 {
295295
}
296296
q.u64()
297297
}
298+
299+
#[no_mangle]
300+
pub extern "C" fn __udivmodsi4(a: u32, b: u32, rem: *mut u32) -> u32 {
301+
let d = __udivsi3(a, b);
302+
if let Some(rem) = unsafe {rem.as_mut()} {
303+
*rem = a - (d*b);
304+
}
305+
return d;
306+
}
307+
308+
#[no_mangle]
309+
pub extern "C" fn __udivsi3(n: u32, d: u32) -> u32 {
310+
let u32_bits = (mem::size_of::<u32>() * U8_BITS) as u32;
311+
312+
// Special cases
313+
if d == 0 {
314+
return 0; // ?!
315+
}
316+
317+
if n == 0 {
318+
return 0;
319+
}
320+
321+
let mut sr = d.leading_zeros().wrapping_sub(n.leading_zeros());
322+
323+
// d > n
324+
if sr > u32_bits - 1 {
325+
return 0;
326+
}
327+
328+
// d == 1
329+
if sr == u32_bits - 1 {
330+
return n;
331+
}
332+
333+
sr = sr + 1;
334+
335+
// 1 <= sr <= u32_bits - 1
336+
let mut q = n << (u32_bits - sr);
337+
let mut r = n >> sr;
338+
339+
let mut carry = 0;
340+
for _ in 0..sr {
341+
// r:q = ((r:q) << 1) | carry
342+
r = (r << 1) | (q >> (u32_bits - 1));
343+
q = (q << 1) | carry;
344+
345+
// carry = 0;
346+
// if r > d {
347+
// r -= d;
348+
// carry = 1;
349+
// }
350+
351+
let s = (d.wrapping_sub(r).wrapping_sub(1)) as i32 >> (u32_bits - 1);
352+
carry = (s & 1) as u32;
353+
r -= d & s as u32;
354+
}
355+
356+
q = (q << 1) | carry;
357+
q
358+
}

src/test.rs

+13
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,16 @@ quickcheck! {
4242
}
4343
}
4444
}
45+
46+
quickcheck! {
47+
fn udivmodsi4(a: u32, b: u32) -> TestResult {
48+
if b == 0 {
49+
TestResult::discard()
50+
} else {
51+
let mut r = 0;
52+
let q = ::__udivmodsi4(a, b, &mut r);
53+
54+
TestResult::from_bool(q * b + r == a)
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)