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
25DEFINE_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
36LOCAL_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
59