xref: /netbsd-src/sys/external/bsd/compiler_rt/dist/lib/builtins/arm/umodsi3.S (revision ef84fd3bd8895f4e6be1e38baf19e6dc3255bc64)
1156cd587Sjoerg/*===-- umodsi3.S - 32-bit unsigned integer modulus -----------------------===//
2156cd587Sjoerg *
3156cd587Sjoerg *                     The LLVM Compiler Infrastructure
4156cd587Sjoerg *
5156cd587Sjoerg * This file is dual licensed under the MIT and the University of Illinois Open
6156cd587Sjoerg * Source Licenses. See LICENSE.TXT for details.
7156cd587Sjoerg *
8156cd587Sjoerg *===----------------------------------------------------------------------===//
9156cd587Sjoerg *
10156cd587Sjoerg * This file implements the __umodsi3 (32-bit unsigned integer modulus)
11156cd587Sjoerg * function for the ARM 32-bit architecture.
12156cd587Sjoerg *
13156cd587Sjoerg *===----------------------------------------------------------------------===*/
14156cd587Sjoerg
15156cd587Sjoerg#include "../assembly.h"
16156cd587Sjoerg
17156cd587Sjoerg	.syntax unified
18156cd587Sjoerg	.text
19190e92d8Sjoerg#if __ARM_ARCH_ISA_THUMB == 2
20190e92d8Sjoerg	.thumb
21190e92d8Sjoerg#endif
22190e92d8Sjoerg
23190e92d8Sjoerg@ unsigned int __umodsi3(unsigned int divident, unsigned int divisor)
24190e92d8Sjoerg@   Calculate and return the remainder of the (unsigned) division.
25190e92d8Sjoerg
26156cd587Sjoerg	.p2align 2
27*ef84fd3bSjoerg#if __ARM_ARCH_ISA_THUMB == 2
28*ef84fd3bSjoergDEFINE_COMPILERRT_THUMB_FUNCTION(__umodsi3)
29*ef84fd3bSjoerg#else
30156cd587SjoergDEFINE_COMPILERRT_FUNCTION(__umodsi3)
31*ef84fd3bSjoerg#endif
32156cd587Sjoerg#if __ARM_ARCH_EXT_IDIV__
33156cd587Sjoerg	tst     r1, r1
34156cd587Sjoerg	beq     LOCAL_LABEL(divby0)
35190e92d8Sjoerg	udiv	r2, r0, r1
36190e92d8Sjoerg	mls 	r0, r2, r1, r0
37156cd587Sjoerg	bx  	lr
38156cd587Sjoerg#else
39156cd587Sjoerg	cmp	r1, #1
40156cd587Sjoerg	bcc	LOCAL_LABEL(divby0)
41190e92d8Sjoerg	ITT(eq)
42156cd587Sjoerg	moveq	r0, #0
43156cd587Sjoerg	JMPc(lr, eq)
44156cd587Sjoerg	cmp	r0, r1
45190e92d8Sjoerg	IT(cc)
46156cd587Sjoerg	JMPc(lr, cc)
47156cd587Sjoerg	/*
48156cd587Sjoerg	 * Implement division using binary long division algorithm.
49156cd587Sjoerg	 *
50156cd587Sjoerg	 * r0 is the numerator, r1 the denominator.
51156cd587Sjoerg	 *
52156cd587Sjoerg	 * The code before JMP computes the correct shift I, so that
53156cd587Sjoerg	 * r0 and (r1 << I) have the highest bit set in the same position.
54156cd587Sjoerg	 * At the time of JMP, ip := .Ldiv0block - 8 * I.
55156cd587Sjoerg	 * This depends on the fixed instruction size of block.
56190e92d8Sjoerg	 * For ARM mode, this is 8 Bytes, for THUMB mode 10 Bytes.
57156cd587Sjoerg	 *
58156cd587Sjoerg	 * block(shift) implements the test-and-update-quotient core.
59156cd587Sjoerg	 * It assumes (r0 << shift) can be computed without overflow and
60156cd587Sjoerg	 * that (r0 << shift) < 2 * r1. The quotient is stored in r3.
61156cd587Sjoerg	 */
62156cd587Sjoerg
63156cd587Sjoerg#  ifdef __ARM_FEATURE_CLZ
64156cd587Sjoerg	clz	ip, r0
65156cd587Sjoerg	clz	r3, r1
66156cd587Sjoerg	/* r0 >= r1 implies clz(r0) <= clz(r1), so ip <= r3. */
67156cd587Sjoerg	sub	r3, r3, ip
68190e92d8Sjoerg#    if __ARM_ARCH_ISA_THUMB == 2
69190e92d8Sjoerg	adr	ip, LOCAL_LABEL(div0block) + 1
70190e92d8Sjoerg	sub	ip, ip, r3, lsl #1
71190e92d8Sjoerg#    else
72156cd587Sjoerg	adr	ip, LOCAL_LABEL(div0block)
73190e92d8Sjoerg#    endif
74156cd587Sjoerg	sub	ip, ip, r3, lsl #3
75156cd587Sjoerg	bx	ip
76156cd587Sjoerg#  else
77190e92d8Sjoerg#    if __ARM_ARCH_ISA_THUMB == 2
78190e92d8Sjoerg#    error THUMB mode requires CLZ or UDIV
79190e92d8Sjoerg#    endif
80156cd587Sjoerg	mov	r2, r0
81156cd587Sjoerg	adr	ip, LOCAL_LABEL(div0block)
82156cd587Sjoerg
83156cd587Sjoerg	lsr	r3, r2, #16
84156cd587Sjoerg	cmp	r3, r1
85156cd587Sjoerg	movhs	r2, r3
86156cd587Sjoerg	subhs	ip, ip, #(16 * 8)
87156cd587Sjoerg
88156cd587Sjoerg	lsr	r3, r2, #8
89156cd587Sjoerg	cmp	r3, r1
90156cd587Sjoerg	movhs	r2, r3
91156cd587Sjoerg	subhs	ip, ip, #(8 * 8)
92156cd587Sjoerg
93156cd587Sjoerg	lsr	r3, r2, #4
94156cd587Sjoerg	cmp	r3, r1
95156cd587Sjoerg	movhs	r2, r3
96156cd587Sjoerg	subhs	ip, #(4 * 8)
97156cd587Sjoerg
98156cd587Sjoerg	lsr	r3, r2, #2
99156cd587Sjoerg	cmp	r3, r1
100156cd587Sjoerg	movhs	r2, r3
101156cd587Sjoerg	subhs	ip, ip, #(2 * 8)
102156cd587Sjoerg
103156cd587Sjoerg	/* Last block, no need to update r2 or r3. */
104156cd587Sjoerg	cmp	r1, r2, lsr #1
105156cd587Sjoerg	subls	ip, ip, #(1 * 8)
106156cd587Sjoerg
107156cd587Sjoerg	JMP(ip)
108156cd587Sjoerg#  endif
109156cd587Sjoerg
110156cd587Sjoerg#define	IMM	#
111156cd587Sjoerg
112156cd587Sjoerg#define block(shift)                                                           \
113156cd587Sjoerg	cmp	r0, r1, lsl IMM shift;                                         \
114190e92d8Sjoerg	IT(hs);                                                                \
115190e92d8Sjoerg	WIDE(subhs)	r0, r0, r1, lsl IMM shift
116156cd587Sjoerg
117156cd587Sjoerg	block(31)
118156cd587Sjoerg	block(30)
119156cd587Sjoerg	block(29)
120156cd587Sjoerg	block(28)
121156cd587Sjoerg	block(27)
122156cd587Sjoerg	block(26)
123156cd587Sjoerg	block(25)
124156cd587Sjoerg	block(24)
125156cd587Sjoerg	block(23)
126156cd587Sjoerg	block(22)
127156cd587Sjoerg	block(21)
128156cd587Sjoerg	block(20)
129156cd587Sjoerg	block(19)
130156cd587Sjoerg	block(18)
131156cd587Sjoerg	block(17)
132156cd587Sjoerg	block(16)
133156cd587Sjoerg	block(15)
134156cd587Sjoerg	block(14)
135156cd587Sjoerg	block(13)
136156cd587Sjoerg	block(12)
137156cd587Sjoerg	block(11)
138156cd587Sjoerg	block(10)
139156cd587Sjoerg	block(9)
140156cd587Sjoerg	block(8)
141156cd587Sjoerg	block(7)
142156cd587Sjoerg	block(6)
143156cd587Sjoerg	block(5)
144156cd587Sjoerg	block(4)
145156cd587Sjoerg	block(3)
146156cd587Sjoerg	block(2)
147156cd587Sjoerg	block(1)
148156cd587SjoergLOCAL_LABEL(div0block):
149156cd587Sjoerg	block(0)
150156cd587Sjoerg	JMP(lr)
151156cd587Sjoerg#endif /* __ARM_ARCH_EXT_IDIV__ */
152156cd587Sjoerg
153156cd587SjoergLOCAL_LABEL(divby0):
154156cd587Sjoerg	mov	r0, #0
155156cd587Sjoerg#ifdef __ARM_EABI__
156156cd587Sjoerg	b	__aeabi_idiv0
157156cd587Sjoerg#else
158156cd587Sjoerg	JMP(lr)
159156cd587Sjoerg#endif
160156cd587Sjoerg
161156cd587SjoergEND_COMPILERRT_FUNCTION(__umodsi3)
162