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 //  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
     59