Skip to content

Commit ca354ff

Browse files
committed
Add tests for ARM division builtins
1 parent aa2561a commit ca354ff

File tree

3 files changed

+86
-5
lines changed

3 files changed

+86
-5
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ See [rust-lang/rust#35437][0].
8282
- [x] ashrdi3.c
8383
- [ ] divdf3.c
8484
- [x] divdi3.c
85+
- [x] divmoddi4.c
86+
- [x] divmodsi4.c
8587
- [ ] divsf3.c
8688
- [x] divsi3.c
8789
- [ ] extendhfsf2.c
@@ -251,8 +253,6 @@ These builtins are never called by LLVM.
251253
- ~~ctzdi2.c~~
252254
- ~~ctzsi2.c~~
253255
- ~~ctzti2.c~~
254-
- ~~divmoddi4.c~~
255-
- ~~divmodsi4.c~~
256256
- ~~ffsdi2.c~~
257257
- ~~ffsti2.c~~
258258
- ~~mulvdi3.c~~

src/arm.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,3 +127,84 @@ pub unsafe extern "C" fn __aeabi_memclr4(dest: *mut u8, n: usize) {
127127
pub unsafe extern "C" fn __aeabi_memclr8(dest: *mut u8, n: usize) {
128128
memset(dest, 0, n);
129129
}
130+
131+
132+
#[cfg(test)]
133+
mod tests {
134+
use quickcheck::TestResult;
135+
use qc::{U32, U64};
136+
137+
quickcheck!{
138+
fn uldivmod(n: U64, d: U64) -> TestResult {
139+
let (n, d) = (n.0, d.0);
140+
if d == 0 {
141+
TestResult::discard()
142+
} else {
143+
let q: u64;
144+
let r: u64;
145+
unsafe {
146+
// The inline asm is a bit tricky here, LLVM will allocate
147+
// both r0 and r1 when we specify a 64-bit value for {r0}.
148+
asm!("bl __aeabi_uldivmod"
149+
: "={r0}" (q), "={r2}" (r)
150+
: "{r0}" (n), "{r2}" (d)
151+
: "r12", "lr", "flags");
152+
}
153+
TestResult::from_bool(q == n / d && r == n % d)
154+
}
155+
}
156+
157+
fn uidivmod(n: U32, d: U32) -> TestResult {
158+
let (n, d) = (n.0, d.0);
159+
if d == 0 {
160+
TestResult::discard()
161+
} else {
162+
let q: u32;
163+
let r: u32;
164+
unsafe {
165+
asm!("bl __aeabi_uidivmod"
166+
: "={r0}" (q), "={r1}" (r)
167+
: "{r0}" (n), "{r1}" (d)
168+
: "r2", "r3", "r12", "lr", "flags");
169+
}
170+
TestResult::from_bool(q == n / d && r == n % d)
171+
}
172+
}
173+
174+
fn ldivmod(n: U64, d: U64) -> TestResult {
175+
let (n, d) = (n.0 as i64, d.0 as i64);
176+
if d == 0 {
177+
TestResult::discard()
178+
} else {
179+
let q: i64;
180+
let r: i64;
181+
unsafe {
182+
// The inline asm is a bit tricky here, LLVM will allocate
183+
// both r0 and r1 when we specify a 64-bit value for {r0}.
184+
asm!("bl __aeabi_ldivmod"
185+
: "={r0}" (q), "={r2}" (r)
186+
: "{r0}" (n), "{r2}" (d)
187+
: "r12", "lr", "flags");
188+
}
189+
TestResult::from_bool(q == n / d && r == n % d)
190+
}
191+
}
192+
193+
fn idivmod(n: U32, d: U32) -> TestResult {
194+
let (n, d) = (n.0 as i32, d.0 as i32);
195+
if d == 0 {
196+
TestResult::discard()
197+
} else {
198+
let q: i32;
199+
let r: i32;
200+
unsafe {
201+
asm!("bl __aeabi_idivmod"
202+
: "={r0}" (q), "={r1}" (r)
203+
: "{r0}" (n), "{r1}" (d)
204+
: "r2", "r3", "r12", "lr", "flags");
205+
}
206+
TestResult::from_bool(q == n / d && r == n % d)
207+
}
208+
}
209+
}
210+
}

src/sdiv.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ macro_rules! mod_ {
3232
}
3333

3434
macro_rules! divmod {
35-
($intrinsic:ident, $div:ident: $ty:ty, $uty:ty) => {
35+
($intrinsic:ident, $div:ident: $ty:ty) => {
3636
/// Returns `a / b` and sets `*rem = n % d`
3737
#[cfg_attr(not(test), no_mangle)]
3838
pub extern "C" fn $intrinsic(a: $ty, b: $ty, rem: &mut $ty) -> $ty {
@@ -47,8 +47,8 @@ div!(__divsi3: i32, u32);
4747
div!(__divdi3: i64, u64);
4848
mod_!(__modsi3: i32, u32);
4949
mod_!(__moddi3: i64, u64);
50-
divmod!(__divmodsi4, __divsi3: i32, u32);
51-
divmod!(__divmoddi4, __divdi3: i64, u64);
50+
divmod!(__divmodsi4, __divsi3: i32);
51+
divmod!(__divmoddi4, __divdi3: i64);
5252

5353
#[cfg(test)]
5454
mod tests {

0 commit comments

Comments
 (0)