1*7c3d14c8STreehugger Robot/*===-- umodsi3.S - 32-bit unsigned integer modulus -----------------------===// 2*7c3d14c8STreehugger Robot * 3*7c3d14c8STreehugger Robot * The LLVM Compiler Infrastructure 4*7c3d14c8STreehugger Robot * 5*7c3d14c8STreehugger Robot * This file is dual licensed under the MIT and the University of Illinois Open 6*7c3d14c8STreehugger Robot * Source Licenses. See LICENSE.TXT for details. 7*7c3d14c8STreehugger Robot * 8*7c3d14c8STreehugger Robot *===----------------------------------------------------------------------===// 9*7c3d14c8STreehugger Robot * 10*7c3d14c8STreehugger Robot * This file implements the __umodsi3 (32-bit unsigned integer modulus) 11*7c3d14c8STreehugger Robot * function for the ARM 32-bit architecture. 12*7c3d14c8STreehugger Robot * 13*7c3d14c8STreehugger Robot *===----------------------------------------------------------------------===*/ 14*7c3d14c8STreehugger Robot 15*7c3d14c8STreehugger Robot#include "../assembly.h" 16*7c3d14c8STreehugger Robot 17*7c3d14c8STreehugger Robot .syntax unified 18*7c3d14c8STreehugger Robot .text 19*7c3d14c8STreehugger Robot#if __ARM_ARCH_ISA_THUMB == 2 20*7c3d14c8STreehugger Robot .thumb 21*7c3d14c8STreehugger Robot#endif 22*7c3d14c8STreehugger Robot 23*7c3d14c8STreehugger Robot@ unsigned int __umodsi3(unsigned int divident, unsigned int divisor) 24*7c3d14c8STreehugger Robot@ Calculate and return the remainder of the (unsigned) division. 25*7c3d14c8STreehugger Robot 26*7c3d14c8STreehugger Robot .p2align 2 27*7c3d14c8STreehugger Robot#if __ARM_ARCH_ISA_THUMB == 2 28*7c3d14c8STreehugger RobotDEFINE_COMPILERRT_THUMB_FUNCTION(__umodsi3) 29*7c3d14c8STreehugger Robot#else 30*7c3d14c8STreehugger RobotDEFINE_COMPILERRT_FUNCTION(__umodsi3) 31*7c3d14c8STreehugger Robot#endif 32*7c3d14c8STreehugger Robot#if __ARM_ARCH_EXT_IDIV__ 33*7c3d14c8STreehugger Robot tst r1, r1 34*7c3d14c8STreehugger Robot beq LOCAL_LABEL(divby0) 35*7c3d14c8STreehugger Robot udiv r2, r0, r1 36*7c3d14c8STreehugger Robot mls r0, r2, r1, r0 37*7c3d14c8STreehugger Robot bx lr 38*7c3d14c8STreehugger Robot#else 39*7c3d14c8STreehugger Robot cmp r1, #1 40*7c3d14c8STreehugger Robot bcc LOCAL_LABEL(divby0) 41*7c3d14c8STreehugger Robot ITT(eq) 42*7c3d14c8STreehugger Robot moveq r0, #0 43*7c3d14c8STreehugger Robot JMPc(lr, eq) 44*7c3d14c8STreehugger Robot cmp r0, r1 45*7c3d14c8STreehugger Robot IT(cc) 46*7c3d14c8STreehugger Robot JMPc(lr, cc) 47*7c3d14c8STreehugger Robot /* 48*7c3d14c8STreehugger Robot * Implement division using binary long division algorithm. 49*7c3d14c8STreehugger Robot * 50*7c3d14c8STreehugger Robot * r0 is the numerator, r1 the denominator. 51*7c3d14c8STreehugger Robot * 52*7c3d14c8STreehugger Robot * The code before JMP computes the correct shift I, so that 53*7c3d14c8STreehugger Robot * r0 and (r1 << I) have the highest bit set in the same position. 54*7c3d14c8STreehugger Robot * At the time of JMP, ip := .Ldiv0block - 8 * I. 55*7c3d14c8STreehugger Robot * This depends on the fixed instruction size of block. 56*7c3d14c8STreehugger Robot * For ARM mode, this is 8 Bytes, for THUMB mode 10 Bytes. 57*7c3d14c8STreehugger Robot * 58*7c3d14c8STreehugger Robot * block(shift) implements the test-and-update-quotient core. 59*7c3d14c8STreehugger Robot * It assumes (r0 << shift) can be computed without overflow and 60*7c3d14c8STreehugger Robot * that (r0 << shift) < 2 * r1. The quotient is stored in r3. 61*7c3d14c8STreehugger Robot */ 62*7c3d14c8STreehugger Robot 63*7c3d14c8STreehugger Robot# ifdef __ARM_FEATURE_CLZ 64*7c3d14c8STreehugger Robot clz ip, r0 65*7c3d14c8STreehugger Robot clz r3, r1 66*7c3d14c8STreehugger Robot /* r0 >= r1 implies clz(r0) <= clz(r1), so ip <= r3. */ 67*7c3d14c8STreehugger Robot sub r3, r3, ip 68*7c3d14c8STreehugger Robot# if __ARM_ARCH_ISA_THUMB == 2 69*7c3d14c8STreehugger Robot adr ip, LOCAL_LABEL(div0block) + 1 70*7c3d14c8STreehugger Robot sub ip, ip, r3, lsl #1 71*7c3d14c8STreehugger Robot# else 72*7c3d14c8STreehugger Robot adr ip, LOCAL_LABEL(div0block) 73*7c3d14c8STreehugger Robot# endif 74*7c3d14c8STreehugger Robot sub ip, ip, r3, lsl #3 75*7c3d14c8STreehugger Robot bx ip 76*7c3d14c8STreehugger Robot# else 77*7c3d14c8STreehugger Robot# if __ARM_ARCH_ISA_THUMB == 2 78*7c3d14c8STreehugger Robot# error THUMB mode requires CLZ or UDIV 79*7c3d14c8STreehugger Robot# endif 80*7c3d14c8STreehugger Robot mov r2, r0 81*7c3d14c8STreehugger Robot adr ip, LOCAL_LABEL(div0block) 82*7c3d14c8STreehugger Robot 83*7c3d14c8STreehugger Robot lsr r3, r2, #16 84*7c3d14c8STreehugger Robot cmp r3, r1 85*7c3d14c8STreehugger Robot movhs r2, r3 86*7c3d14c8STreehugger Robot subhs ip, ip, #(16 * 8) 87*7c3d14c8STreehugger Robot 88*7c3d14c8STreehugger Robot lsr r3, r2, #8 89*7c3d14c8STreehugger Robot cmp r3, r1 90*7c3d14c8STreehugger Robot movhs r2, r3 91*7c3d14c8STreehugger Robot subhs ip, ip, #(8 * 8) 92*7c3d14c8STreehugger Robot 93*7c3d14c8STreehugger Robot lsr r3, r2, #4 94*7c3d14c8STreehugger Robot cmp r3, r1 95*7c3d14c8STreehugger Robot movhs r2, r3 96*7c3d14c8STreehugger Robot subhs ip, #(4 * 8) 97*7c3d14c8STreehugger Robot 98*7c3d14c8STreehugger Robot lsr r3, r2, #2 99*7c3d14c8STreehugger Robot cmp r3, r1 100*7c3d14c8STreehugger Robot movhs r2, r3 101*7c3d14c8STreehugger Robot subhs ip, ip, #(2 * 8) 102*7c3d14c8STreehugger Robot 103*7c3d14c8STreehugger Robot /* Last block, no need to update r2 or r3. */ 104*7c3d14c8STreehugger Robot cmp r1, r2, lsr #1 105*7c3d14c8STreehugger Robot subls ip, ip, #(1 * 8) 106*7c3d14c8STreehugger Robot 107*7c3d14c8STreehugger Robot JMP(ip) 108*7c3d14c8STreehugger Robot# endif 109*7c3d14c8STreehugger Robot 110*7c3d14c8STreehugger Robot#define IMM # 111*7c3d14c8STreehugger Robot 112*7c3d14c8STreehugger Robot#define block(shift) \ 113*7c3d14c8STreehugger Robot cmp r0, r1, lsl IMM shift; \ 114*7c3d14c8STreehugger Robot IT(hs); \ 115*7c3d14c8STreehugger Robot WIDE(subhs) r0, r0, r1, lsl IMM shift 116*7c3d14c8STreehugger Robot 117*7c3d14c8STreehugger Robot block(31) 118*7c3d14c8STreehugger Robot block(30) 119*7c3d14c8STreehugger Robot block(29) 120*7c3d14c8STreehugger Robot block(28) 121*7c3d14c8STreehugger Robot block(27) 122*7c3d14c8STreehugger Robot block(26) 123*7c3d14c8STreehugger Robot block(25) 124*7c3d14c8STreehugger Robot block(24) 125*7c3d14c8STreehugger Robot block(23) 126*7c3d14c8STreehugger Robot block(22) 127*7c3d14c8STreehugger Robot block(21) 128*7c3d14c8STreehugger Robot block(20) 129*7c3d14c8STreehugger Robot block(19) 130*7c3d14c8STreehugger Robot block(18) 131*7c3d14c8STreehugger Robot block(17) 132*7c3d14c8STreehugger Robot block(16) 133*7c3d14c8STreehugger Robot block(15) 134*7c3d14c8STreehugger Robot block(14) 135*7c3d14c8STreehugger Robot block(13) 136*7c3d14c8STreehugger Robot block(12) 137*7c3d14c8STreehugger Robot block(11) 138*7c3d14c8STreehugger Robot block(10) 139*7c3d14c8STreehugger Robot block(9) 140*7c3d14c8STreehugger Robot block(8) 141*7c3d14c8STreehugger Robot block(7) 142*7c3d14c8STreehugger Robot block(6) 143*7c3d14c8STreehugger Robot block(5) 144*7c3d14c8STreehugger Robot block(4) 145*7c3d14c8STreehugger Robot block(3) 146*7c3d14c8STreehugger Robot block(2) 147*7c3d14c8STreehugger Robot block(1) 148*7c3d14c8STreehugger RobotLOCAL_LABEL(div0block): 149*7c3d14c8STreehugger Robot block(0) 150*7c3d14c8STreehugger Robot JMP(lr) 151*7c3d14c8STreehugger Robot#endif /* __ARM_ARCH_EXT_IDIV__ */ 152*7c3d14c8STreehugger Robot 153*7c3d14c8STreehugger RobotLOCAL_LABEL(divby0): 154*7c3d14c8STreehugger Robot mov r0, #0 155*7c3d14c8STreehugger Robot#ifdef __ARM_EABI__ 156*7c3d14c8STreehugger Robot b __aeabi_idiv0 157*7c3d14c8STreehugger Robot#else 158*7c3d14c8STreehugger Robot JMP(lr) 159*7c3d14c8STreehugger Robot#endif 160*7c3d14c8STreehugger Robot 161*7c3d14c8STreehugger RobotEND_COMPILERRT_FUNCTION(__umodsi3) 162*7c3d14c8STreehugger Robot 163*7c3d14c8STreehugger RobotNO_EXEC_STACK_DIRECTIVE 164*7c3d14c8STreehugger Robot 165