1 //===-- umodsi3.S - 32-bit unsigned integer modulus -----------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements the __umodsi3 (32-bit unsigned integer modulus)
10 // function for the ARM 32-bit architecture.
12 //===----------------------------------------------------------------------===//
14 #include "../assembly.h"
20 @ unsigned int __umodsi3(unsigned int divident, unsigned int divisor)
21 @ Calculate and return the remainder of the (unsigned) division.
24 DEFINE_COMPILERRT_FUNCTION(__umodsi3)
25 #if __ARM_ARCH_EXT_IDIV__
27 beq LOCAL_LABEL(divby0)
33 bcc LOCAL_LABEL(divby0)
41 // Implement division using binary long division algorithm.
43 // r0 is the numerator, r1 the denominator.
45 // The code before JMP computes the correct shift I, so that
46 // r0 and (r1 << I) have the highest bit set in the same position.
47 // At the time of JMP, ip := .Ldiv0block - 8 * I.
48 // This depends on the fixed instruction size of block.
49 // For ARM mode, this is 8 Bytes, for THUMB mode 10 Bytes.
51 // block(shift) implements the test-and-update-quotient core.
52 // It assumes (r0 << shift) can be computed without overflow and
53 // that (r0 << shift) < 2 * r1. The quotient is stored in r3.
55 # ifdef __ARM_FEATURE_CLZ
58 // r0 >= r1 implies clz(r0) <= clz(r1), so ip <= r3.
60 # if defined(USE_THUMB_2)
61 adr ip, LOCAL_LABEL(div0block) + 1
62 sub ip, ip, r3, lsl #1
64 adr ip, LOCAL_LABEL(div0block)
66 sub ip, ip, r3, lsl #3
69 # if defined(USE_THUMB_2)
70 # error THUMB mode requires CLZ or UDIV
73 adr ip, LOCAL_LABEL(div0block)
78 subhs ip, ip, #(16 * 8)
83 subhs ip, ip, #(8 * 8)
93 subhs ip, ip, #(2 * 8)
95 // Last block, no need to update r2 or r3.
97 subls ip, ip, #(1 * 8)
104 #define block(shift) \
105 cmp r0, r1, lsl IMM shift; \
107 WIDE(subhs) r0, r0, r1, lsl IMM shift
140 LOCAL_LABEL(div0block):
143 #endif // __ARM_ARCH_EXT_IDIV__
153 END_COMPILERRT_FUNCTION(__umodsi3)
155 NO_EXEC_STACK_DIRECTIVE