xref: /aosp_15_r20/external/compiler-rt/lib/builtins/arm/umodsi3.S (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
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