1 |
/*===-- umodsi3.S - 32-bit unsigned integer modulus -----------------------===// |
2 |
* |
3 |
* The LLVM Compiler Infrastructure |
4 |
* |
5 |
* This file is dual licensed under the MIT and the University of Illinois Open |
6 |
* Source Licenses. See LICENSE.TXT for details. |
7 |
* |
8 |
*===----------------------------------------------------------------------===// |
9 |
* |
10 |
* This file implements the __umodsi3 (32-bit unsigned integer modulus) |
11 |
* function for the ARM architecture. A naive digit-by-digit computation is |
12 |
* employed for simplicity. |
13 |
* |
14 |
*===----------------------------------------------------------------------===*/ |
15 |
|
16 |
#include "../assembly.h" |
17 |
|
18 |
#define a r0 |
19 |
#define b r1 |
20 |
#define r r2 |
21 |
#define i r3 |
22 |
|
23 |
.syntax unified |
24 |
.align 3 |
25 |
DEFINE_COMPILERRT_FUNCTION(__umodsi3) |
26 |
// We use a simple digit by digit algorithm; before we get into the actual |
27 |
// divide loop, we must calculate the left-shift amount necessary to align |
28 |
// the MSB of the divisor with that of the dividend. |
29 |
clz r2, a |
30 |
tst b, b // detect b == 0 |
31 |
clz r3, b |
32 |
bxeq lr // return a if b == 0 |
33 |
subs i, r3, r2 |
34 |
bxlt lr // return a if MSB(a) < MSB(b) |
35 |
|
36 |
LOCAL_LABEL(mainLoop): |
37 |
// This loop basically implements the following: |
38 |
// |
39 |
// do { |
40 |
// if (a >= b << i) { |
41 |
// a -= b << i; |
42 |
// if (a == 0) break; |
43 |
// } |
44 |
// } while (--i) |
45 |
// |
46 |
// Note that this does not perform the final iteration (i == 0); by doing it |
47 |
// this way, we can merge the two branches which is a substantial win for |
48 |
// such a tight loop on current ARM architectures. |
49 |
subs r, a, b, lsl i |
50 |
movhs a, r |
51 |
subsne i, i, #1 |
52 |
bhi LOCAL_LABEL(mainLoop) |
53 |
|
54 |
// Do the final test subtraction and update of remainder (i == 0), as it is |
55 |
// not performed in the main loop. |
56 |
subs r, a, b |
57 |
movhs a, r |
58 |
bx lr |