1 /*===-- umodsi3.S - 32-bit unsigned integer modulus -----------------------===//
3 * The LLVM Compiler Infrastructure
5 * This file is dual licensed under the MIT and the University of Illinois Open
6 * Source Licenses. See LICENSE.TXT for details.
8 *===----------------------------------------------------------------------===//
10 * This file implements the __umodsi3 (32-bit unsigned integer modulus)
11 * function for the ARM 32-bit architecture.
13 *===----------------------------------------------------------------------===*/
15 #include "../assembly.h"
21 @ unsigned int __umodsi3(unsigned int divident, unsigned int divisor)
22 @ Calculate and return the remainder of the (unsigned) division.
25 DEFINE_COMPILERRT_FUNCTION(__umodsi3)
26 #if __ARM_ARCH_EXT_IDIV__
28 beq LOCAL_LABEL(divby0)
34 bcc LOCAL_LABEL(divby0)
42 * Implement division using binary long division algorithm.
44 * r0 is the numerator, r1 the denominator.
46 * The code before JMP computes the correct shift I, so that
47 * r0 and (r1 << I) have the highest bit set in the same position.
48 * At the time of JMP, ip := .Ldiv0block - 8 * I.
49 * This depends on the fixed instruction size of block.
50 * For ARM mode, this is 8 Bytes, for THUMB mode 10 Bytes.
52 * block(shift) implements the test-and-update-quotient core.
53 * It assumes (r0 << shift) can be computed without overflow and
54 * that (r0 << shift) < 2 * r1. The quotient is stored in r3.
57 # ifdef __ARM_FEATURE_CLZ
60 /* r0 >= r1 implies clz(r0) <= clz(r1), so ip <= r3. */
62 # if defined(USE_THUMB_2)
63 adr ip, LOCAL_LABEL(div0block) + 1
64 sub ip, ip, r3, lsl #1
66 adr ip, LOCAL_LABEL(div0block)
68 sub ip, ip, r3, lsl #3
71 # if defined(USE_THUMB_2)
72 # error THUMB mode requires CLZ or UDIV
75 adr ip, LOCAL_LABEL(div0block)
80 subhs ip, ip, #(16 * 8)
85 subhs ip, ip, #(8 * 8)
95 subhs ip, ip, #(2 * 8)
97 /* Last block, no need to update r2 or r3. */
99 subls ip, ip, #(1 * 8)
106 #define block(shift) \
107 cmp r0, r1, lsl IMM shift; \
109 WIDE(subhs) r0, r0, r1, lsl IMM shift
142 LOCAL_LABEL(div0block):
145 #endif /* __ARM_ARCH_EXT_IDIV__ */
155 END_COMPILERRT_FUNCTION(__umodsi3)
157 NO_EXEC_STACK_DIRECTIVE