Home | History | Annotate | Download | only in arm
      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 #if __ARM_ARCH_7S__
     27 	tst     r1, r1
     28 	beq     LOCAL_LABEL(divzero)
     29 	udiv	r2, r0, r1
     30 	mls     r0, r2, r1, r0
     31 	bx      lr
     32 LOCAL_LABEL(divzero):
     33 	mov     r0, #0
     34 	bx      lr
     35 #else
     36 //  We use a simple digit by digit algorithm; before we get into the actual
     37 //  divide loop, we must calculate the left-shift amount necessary to align
     38 //  the MSB of the divisor with that of the dividend.
     39     clz     r2,     a
     40     tst     b,      b       // detect b == 0
     41     clz     r3,     b
     42     bxeq    lr              // return a if b == 0
     43     subs    i,      r3, r2
     44     bxlt    lr              // return a if MSB(a) < MSB(b)
     45 
     46 LOCAL_LABEL(mainLoop):
     47 //  This loop basically implements the following:
     48 //
     49 //  do {
     50 //      if (a >= b << i) {
     51 //          a -= b << i;
     52 //          if (a == 0) break;
     53 //      }
     54 //  } while (--i)
     55 //
     56 //  Note that this does not perform the final iteration (i == 0); by doing it
     57 //  this way, we can merge the two branches which is a substantial win for
     58 //  such a tight loop on current ARM architectures.
     59     subs    r,      a,  b, lsl i
     60     movhs   a,      r
     61     subsne  i,      i, #1
     62     bhi     LOCAL_LABEL(mainLoop)
     63 
     64 //  Do the final test subtraction and update of remainder (i == 0), as it is
     65 //  not performed in the main loop.
     66     subs    r,      a,  b
     67     movhs   a,      r
     68     bx      lr
     69 #endif
     70