udivsi3.S revision 5d71de26cedae3dafc17449fe0182045c0bd20e8
14a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project/*===-- udivsi3.S - 32-bit unsigned integer divide ------------------------===//
24a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *
34a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *                     The LLVM Compiler Infrastructure
44a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *
54a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * This file is dual licensed under the MIT and the University of Illinois Open
64a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * Source Licenses. See LICENSE.TXT for details.
74a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *
84a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *===----------------------------------------------------------------------===//
94a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *
104a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * This file implements the __udivsi3 (32-bit unsigned integer divide)
114a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project * function for the ARM 32-bit architecture.
124a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *
134a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project *===----------------------------------------------------------------------===*/
144a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
154a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#include "../assembly.h"
164a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
174a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	.syntax unified
184a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	.text
194a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
204a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	.p2align 2
214a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectDEFINE_AEABI_FUNCTION_ALIAS(__aeabi_uidiv, __udivsi3)
224a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source ProjectDEFINE_COMPILERRT_FUNCTION(__udivsi3)
234a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#if __ARM_ARCH_EXT_IDIV__
244a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	tst     r1, r1
254a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	beq     LOCAL_LABEL(divby0)
264a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	mov 	r3, r0
274a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	udiv	r0, r3, r1
284a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	mls 	r1, r0, r1, r3
294a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	bx  	lr
304a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#else
314a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	cmp	r1, #1
324a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	bcc	LOCAL_LABEL(divby0)
334a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	JMPc(lr, eq)
344a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	cmp	r0, r1
354a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	movcc	r0, #0
364a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	JMPc(lr, cc)
374a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	/*
384a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 * Implement division using binary long division algorithm.
394a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 *
404a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 * r0 is the numerator, r1 the denominator.
414a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 *
424a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 * The code before JMP computes the correct shift I, so that
434a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 * r0 and (r1 << I) have the highest bit set in the same position.
444a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 * At the time of JMP, ip := .Ldiv0block - 12 * I.
454a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 * This depends on the fixed instruction size of block.
464a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 *
474a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 * block(shift) implements the test-and-update-quotient core.
484a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 * It assumes (r0 << shift) can be computed without overflow and
494a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 * that (r0 << shift) < 2 * r1. The quotient is stored in r3.
504a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	 */
514a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
524a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#  ifdef __ARM_FEATURE_CLZ
534a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	clz	ip, r0
544a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	clz	r3, r1
554a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	/* r0 >= r1 implies clz(r0) <= clz(r1), so ip <= r3. */
564a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	sub	r3, r3, ip
574a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	adr	ip, LOCAL_LABEL(div0block)
584a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	sub	ip, ip, r3, lsl #2
594a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	sub	ip, ip, r3, lsl #3
604a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	mov	r3, #0
614a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	bx	ip
624a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#  else
634a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	mov	r2, r0
644a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	adr	ip, LOCAL_LABEL(div0block)
654a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
664a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	lsr	r3, r2, #16
674a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	cmp	r3, r1
684a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	movhs	r2, r3
694a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	subhs	ip, ip, #(16 * 12)
704a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
714a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	lsr	r3, r2, #8
724a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	cmp	r3, r1
734a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	movhs	r2, r3
744a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	subhs	ip, ip, #(8 * 12)
754a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
764a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	lsr	r3, r2, #4
774a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	cmp	r3, r1
784a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	movhs	r2, r3
794a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	subhs	ip, #(4 * 12)
804a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
814a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	lsr	r3, r2, #2
824a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	cmp	r3, r1
834a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	movhs	r2, r3
844a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	subhs	ip, ip, #(2 * 12)
854a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
864a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	/* Last block, no need to update r2 or r3. */
874a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	cmp	r1, r2, lsr #1
884a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	subls	ip, ip, #(1 * 12)
894a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
904a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	mov	r3, #0
914a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
924a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	JMP(ip)
934a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#  endif
944a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
954a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define	IMM	#
964a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project
974a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project#define block(shift) \
984a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	cmp	r0, r1, lsl IMM shift; \
994a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	addhs	r3, r3, IMM (1 << shift); \
1004a68b3365c8c50aa93505e99ead2565ab73dcdb0The Android Open Source Project	subhs	r0, r0, r1, lsl IMM shift
101
102	block(31)
103	block(30)
104	block(29)
105	block(28)
106	block(27)
107	block(26)
108	block(25)
109	block(24)
110	block(23)
111	block(22)
112	block(21)
113	block(20)
114	block(19)
115	block(18)
116	block(17)
117	block(16)
118	block(15)
119	block(14)
120	block(13)
121	block(12)
122	block(11)
123	block(10)
124	block(9)
125	block(8)
126	block(7)
127	block(6)
128	block(5)
129	block(4)
130	block(3)
131	block(2)
132	block(1)
133LOCAL_LABEL(div0block):
134	block(0)
135
136	mov	r0, r3
137	JMP(lr)
138#endif /* __ARM_ARCH_EXT_IDIV__ */
139
140LOCAL_LABEL(divby0):
141	mov	r0, #0
142#ifdef __ARM_EABI__
143	b	__aeabi_idiv0
144#else
145	JMP(lr)
146#endif
147
148END_COMPILERRT_FUNCTION(__udivsi3)
149