18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Author: Nicolas Pitre <nico@fluxnic.net>
58c2ecf20Sopenharmony_ci *   - contributed to gcc-3.4 on Sep 30, 2003
68c2ecf20Sopenharmony_ci *   - adapted for the Linux kernel on Oct 2, 2003
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci/* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ciThis file is free software; you can redistribute it and/or modify it
128c2ecf20Sopenharmony_ciunder the terms of the GNU General Public License as published by the
138c2ecf20Sopenharmony_ciFree Software Foundation; either version 2, or (at your option) any
148c2ecf20Sopenharmony_cilater version.
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ciIn addition to the permissions in the GNU General Public License, the
178c2ecf20Sopenharmony_ciFree Software Foundation gives you unlimited permission to link the
188c2ecf20Sopenharmony_cicompiled version of this file into combinations with other programs,
198c2ecf20Sopenharmony_ciand to distribute those combinations without any restriction coming
208c2ecf20Sopenharmony_cifrom the use of this file.  (The General Public License restrictions
218c2ecf20Sopenharmony_cido apply in other respects; for example, they cover modification of
228c2ecf20Sopenharmony_cithe file, and distribution when not linked into a combine
238c2ecf20Sopenharmony_ciexecutable.)
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ciThis file is distributed in the hope that it will be useful, but
268c2ecf20Sopenharmony_ciWITHOUT ANY WARRANTY; without even the implied warranty of
278c2ecf20Sopenharmony_ciMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
288c2ecf20Sopenharmony_ciGeneral Public License for more details.
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ciYou should have received a copy of the GNU General Public License
318c2ecf20Sopenharmony_cialong with this program; see the file COPYING.  If not, write to
328c2ecf20Sopenharmony_cithe Free Software Foundation, 59 Temple Place - Suite 330,
338c2ecf20Sopenharmony_ciBoston, MA 02111-1307, USA.  */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#include <linux/linkage.h>
378c2ecf20Sopenharmony_ci#include <asm/assembler.h>
388c2ecf20Sopenharmony_ci#include <asm/unwind.h>
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci.macro ARM_DIV_BODY dividend, divisor, result, curbit
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 5
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	clz	\curbit, \divisor
458c2ecf20Sopenharmony_ci	clz	\result, \dividend
468c2ecf20Sopenharmony_ci	sub	\result, \curbit, \result
478c2ecf20Sopenharmony_ci	mov	\curbit, #1
488c2ecf20Sopenharmony_ci	mov	\divisor, \divisor, lsl \result
498c2ecf20Sopenharmony_ci	mov	\curbit, \curbit, lsl \result
508c2ecf20Sopenharmony_ci	mov	\result, #0
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#else
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci	@ Initially shift the divisor left 3 bits if possible,
558c2ecf20Sopenharmony_ci	@ set curbit accordingly.  This allows for curbit to be located
568c2ecf20Sopenharmony_ci	@ at the left end of each 4 bit nibbles in the division loop
578c2ecf20Sopenharmony_ci	@ to save one loop in most cases.
588c2ecf20Sopenharmony_ci	tst	\divisor, #0xe0000000
598c2ecf20Sopenharmony_ci	moveq	\divisor, \divisor, lsl #3
608c2ecf20Sopenharmony_ci	moveq	\curbit, #8
618c2ecf20Sopenharmony_ci	movne	\curbit, #1
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	@ Unless the divisor is very big, shift it up in multiples of
648c2ecf20Sopenharmony_ci	@ four bits, since this is the amount of unwinding in the main
658c2ecf20Sopenharmony_ci	@ division loop.  Continue shifting until the divisor is
668c2ecf20Sopenharmony_ci	@ larger than the dividend.
678c2ecf20Sopenharmony_ci1:	cmp	\divisor, #0x10000000
688c2ecf20Sopenharmony_ci	cmplo	\divisor, \dividend
698c2ecf20Sopenharmony_ci	movlo	\divisor, \divisor, lsl #4
708c2ecf20Sopenharmony_ci	movlo	\curbit, \curbit, lsl #4
718c2ecf20Sopenharmony_ci	blo	1b
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci	@ For very big divisors, we must shift it a bit at a time, or
748c2ecf20Sopenharmony_ci	@ we will be in danger of overflowing.
758c2ecf20Sopenharmony_ci1:	cmp	\divisor, #0x80000000
768c2ecf20Sopenharmony_ci	cmplo	\divisor, \dividend
778c2ecf20Sopenharmony_ci	movlo	\divisor, \divisor, lsl #1
788c2ecf20Sopenharmony_ci	movlo	\curbit, \curbit, lsl #1
798c2ecf20Sopenharmony_ci	blo	1b
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci	mov	\result, #0
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci#endif
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci	@ Division loop
868c2ecf20Sopenharmony_ci1:	cmp	\dividend, \divisor
878c2ecf20Sopenharmony_ci	subhs	\dividend, \dividend, \divisor
888c2ecf20Sopenharmony_ci	orrhs	\result,   \result,   \curbit
898c2ecf20Sopenharmony_ci	cmp	\dividend, \divisor,  lsr #1
908c2ecf20Sopenharmony_ci	subhs	\dividend, \dividend, \divisor, lsr #1
918c2ecf20Sopenharmony_ci	orrhs	\result,   \result,   \curbit,  lsr #1
928c2ecf20Sopenharmony_ci	cmp	\dividend, \divisor,  lsr #2
938c2ecf20Sopenharmony_ci	subhs	\dividend, \dividend, \divisor, lsr #2
948c2ecf20Sopenharmony_ci	orrhs	\result,   \result,   \curbit,  lsr #2
958c2ecf20Sopenharmony_ci	cmp	\dividend, \divisor,  lsr #3
968c2ecf20Sopenharmony_ci	subhs	\dividend, \dividend, \divisor, lsr #3
978c2ecf20Sopenharmony_ci	orrhs	\result,   \result,   \curbit,  lsr #3
988c2ecf20Sopenharmony_ci	cmp	\dividend, #0			@ Early termination?
998c2ecf20Sopenharmony_ci	movsne	\curbit,   \curbit,  lsr #4	@ No, any more bits to do?
1008c2ecf20Sopenharmony_ci	movne	\divisor,  \divisor, lsr #4
1018c2ecf20Sopenharmony_ci	bne	1b
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci.endm
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci.macro ARM_DIV2_ORDER divisor, order
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 5
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	clz	\order, \divisor
1118c2ecf20Sopenharmony_ci	rsb	\order, \order, #31
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci#else
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci	cmp	\divisor, #(1 << 16)
1168c2ecf20Sopenharmony_ci	movhs	\divisor, \divisor, lsr #16
1178c2ecf20Sopenharmony_ci	movhs	\order, #16
1188c2ecf20Sopenharmony_ci	movlo	\order, #0
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	cmp	\divisor, #(1 << 8)
1218c2ecf20Sopenharmony_ci	movhs	\divisor, \divisor, lsr #8
1228c2ecf20Sopenharmony_ci	addhs	\order, \order, #8
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci	cmp	\divisor, #(1 << 4)
1258c2ecf20Sopenharmony_ci	movhs	\divisor, \divisor, lsr #4
1268c2ecf20Sopenharmony_ci	addhs	\order, \order, #4
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ci	cmp	\divisor, #(1 << 2)
1298c2ecf20Sopenharmony_ci	addhi	\order, \order, #3
1308c2ecf20Sopenharmony_ci	addls	\order, \order, \divisor, lsr #1
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci#endif
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci.endm
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci
1378c2ecf20Sopenharmony_ci.macro ARM_MOD_BODY dividend, divisor, order, spare
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ >= 5
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_ci	clz	\order, \divisor
1428c2ecf20Sopenharmony_ci	clz	\spare, \dividend
1438c2ecf20Sopenharmony_ci	sub	\order, \order, \spare
1448c2ecf20Sopenharmony_ci	mov	\divisor, \divisor, lsl \order
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci#else
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	mov	\order, #0
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	@ Unless the divisor is very big, shift it up in multiples of
1518c2ecf20Sopenharmony_ci	@ four bits, since this is the amount of unwinding in the main
1528c2ecf20Sopenharmony_ci	@ division loop.  Continue shifting until the divisor is
1538c2ecf20Sopenharmony_ci	@ larger than the dividend.
1548c2ecf20Sopenharmony_ci1:	cmp	\divisor, #0x10000000
1558c2ecf20Sopenharmony_ci	cmplo	\divisor, \dividend
1568c2ecf20Sopenharmony_ci	movlo	\divisor, \divisor, lsl #4
1578c2ecf20Sopenharmony_ci	addlo	\order, \order, #4
1588c2ecf20Sopenharmony_ci	blo	1b
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	@ For very big divisors, we must shift it a bit at a time, or
1618c2ecf20Sopenharmony_ci	@ we will be in danger of overflowing.
1628c2ecf20Sopenharmony_ci1:	cmp	\divisor, #0x80000000
1638c2ecf20Sopenharmony_ci	cmplo	\divisor, \dividend
1648c2ecf20Sopenharmony_ci	movlo	\divisor, \divisor, lsl #1
1658c2ecf20Sopenharmony_ci	addlo	\order, \order, #1
1668c2ecf20Sopenharmony_ci	blo	1b
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci#endif
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	@ Perform all needed subtractions to keep only the reminder.
1718c2ecf20Sopenharmony_ci	@ Do comparisons in batch of 4 first.
1728c2ecf20Sopenharmony_ci	subs	\order, \order, #3		@ yes, 3 is intended here
1738c2ecf20Sopenharmony_ci	blt	2f
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci1:	cmp	\dividend, \divisor
1768c2ecf20Sopenharmony_ci	subhs	\dividend, \dividend, \divisor
1778c2ecf20Sopenharmony_ci	cmp	\dividend, \divisor,  lsr #1
1788c2ecf20Sopenharmony_ci	subhs	\dividend, \dividend, \divisor, lsr #1
1798c2ecf20Sopenharmony_ci	cmp	\dividend, \divisor,  lsr #2
1808c2ecf20Sopenharmony_ci	subhs	\dividend, \dividend, \divisor, lsr #2
1818c2ecf20Sopenharmony_ci	cmp	\dividend, \divisor,  lsr #3
1828c2ecf20Sopenharmony_ci	subhs	\dividend, \dividend, \divisor, lsr #3
1838c2ecf20Sopenharmony_ci	cmp	\dividend, #1
1848c2ecf20Sopenharmony_ci	mov	\divisor, \divisor, lsr #4
1858c2ecf20Sopenharmony_ci	subsge	\order, \order, #4
1868c2ecf20Sopenharmony_ci	bge	1b
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	tst	\order, #3
1898c2ecf20Sopenharmony_ci	teqne	\dividend, #0
1908c2ecf20Sopenharmony_ci	beq	5f
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	@ Either 1, 2 or 3 comparison/subtractions are left.
1938c2ecf20Sopenharmony_ci2:	cmn	\order, #2
1948c2ecf20Sopenharmony_ci	blt	4f
1958c2ecf20Sopenharmony_ci	beq	3f
1968c2ecf20Sopenharmony_ci	cmp	\dividend, \divisor
1978c2ecf20Sopenharmony_ci	subhs	\dividend, \dividend, \divisor
1988c2ecf20Sopenharmony_ci	mov	\divisor,  \divisor,  lsr #1
1998c2ecf20Sopenharmony_ci3:	cmp	\dividend, \divisor
2008c2ecf20Sopenharmony_ci	subhs	\dividend, \dividend, \divisor
2018c2ecf20Sopenharmony_ci	mov	\divisor,  \divisor,  lsr #1
2028c2ecf20Sopenharmony_ci4:	cmp	\dividend, \divisor
2038c2ecf20Sopenharmony_ci	subhs	\dividend, \dividend, \divisor
2048c2ecf20Sopenharmony_ci5:
2058c2ecf20Sopenharmony_ci.endm
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_PATCH_IDIV
2098c2ecf20Sopenharmony_ci	.align	3
2108c2ecf20Sopenharmony_ci#endif
2118c2ecf20Sopenharmony_ci
2128c2ecf20Sopenharmony_ciENTRY(__udivsi3)
2138c2ecf20Sopenharmony_ciENTRY(__aeabi_uidiv)
2148c2ecf20Sopenharmony_ciUNWIND(.fnstart)
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	subs	r2, r1, #1
2178c2ecf20Sopenharmony_ci	reteq	lr
2188c2ecf20Sopenharmony_ci	bcc	Ldiv0
2198c2ecf20Sopenharmony_ci	cmp	r0, r1
2208c2ecf20Sopenharmony_ci	bls	11f
2218c2ecf20Sopenharmony_ci	tst	r1, r2
2228c2ecf20Sopenharmony_ci	beq	12f
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	ARM_DIV_BODY r0, r1, r2, r3
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	mov	r0, r2
2278c2ecf20Sopenharmony_ci	ret	lr
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci11:	moveq	r0, #1
2308c2ecf20Sopenharmony_ci	movne	r0, #0
2318c2ecf20Sopenharmony_ci	ret	lr
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci12:	ARM_DIV2_ORDER r1, r2
2348c2ecf20Sopenharmony_ci
2358c2ecf20Sopenharmony_ci	mov	r0, r0, lsr r2
2368c2ecf20Sopenharmony_ci	ret	lr
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_ciUNWIND(.fnend)
2398c2ecf20Sopenharmony_ciENDPROC(__udivsi3)
2408c2ecf20Sopenharmony_ciENDPROC(__aeabi_uidiv)
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ciENTRY(__umodsi3)
2438c2ecf20Sopenharmony_ciUNWIND(.fnstart)
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	subs	r2, r1, #1			@ compare divisor with 1
2468c2ecf20Sopenharmony_ci	bcc	Ldiv0
2478c2ecf20Sopenharmony_ci	cmpne	r0, r1				@ compare dividend with divisor
2488c2ecf20Sopenharmony_ci	moveq   r0, #0
2498c2ecf20Sopenharmony_ci	tsthi	r1, r2				@ see if divisor is power of 2
2508c2ecf20Sopenharmony_ci	andeq	r0, r0, r2
2518c2ecf20Sopenharmony_ci	retls	lr
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_ci	ARM_MOD_BODY r0, r1, r2, r3
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	ret	lr
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ciUNWIND(.fnend)
2588c2ecf20Sopenharmony_ciENDPROC(__umodsi3)
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM_PATCH_IDIV
2618c2ecf20Sopenharmony_ci	.align 3
2628c2ecf20Sopenharmony_ci#endif
2638c2ecf20Sopenharmony_ci
2648c2ecf20Sopenharmony_ciENTRY(__divsi3)
2658c2ecf20Sopenharmony_ciENTRY(__aeabi_idiv)
2668c2ecf20Sopenharmony_ciUNWIND(.fnstart)
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	cmp	r1, #0
2698c2ecf20Sopenharmony_ci	eor	ip, r0, r1			@ save the sign of the result.
2708c2ecf20Sopenharmony_ci	beq	Ldiv0
2718c2ecf20Sopenharmony_ci	rsbmi	r1, r1, #0			@ loops below use unsigned.
2728c2ecf20Sopenharmony_ci	subs	r2, r1, #1			@ division by 1 or -1 ?
2738c2ecf20Sopenharmony_ci	beq	10f
2748c2ecf20Sopenharmony_ci	movs	r3, r0
2758c2ecf20Sopenharmony_ci	rsbmi	r3, r0, #0			@ positive dividend value
2768c2ecf20Sopenharmony_ci	cmp	r3, r1
2778c2ecf20Sopenharmony_ci	bls	11f
2788c2ecf20Sopenharmony_ci	tst	r1, r2				@ divisor is power of 2 ?
2798c2ecf20Sopenharmony_ci	beq	12f
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci	ARM_DIV_BODY r3, r1, r0, r2
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	cmp	ip, #0
2848c2ecf20Sopenharmony_ci	rsbmi	r0, r0, #0
2858c2ecf20Sopenharmony_ci	ret	lr
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci10:	teq	ip, r0				@ same sign ?
2888c2ecf20Sopenharmony_ci	rsbmi	r0, r0, #0
2898c2ecf20Sopenharmony_ci	ret	lr
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci11:	movlo	r0, #0
2928c2ecf20Sopenharmony_ci	moveq	r0, ip, asr #31
2938c2ecf20Sopenharmony_ci	orreq	r0, r0, #1
2948c2ecf20Sopenharmony_ci	ret	lr
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci12:	ARM_DIV2_ORDER r1, r2
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	cmp	ip, #0
2998c2ecf20Sopenharmony_ci	mov	r0, r3, lsr r2
3008c2ecf20Sopenharmony_ci	rsbmi	r0, r0, #0
3018c2ecf20Sopenharmony_ci	ret	lr
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ciUNWIND(.fnend)
3048c2ecf20Sopenharmony_ciENDPROC(__divsi3)
3058c2ecf20Sopenharmony_ciENDPROC(__aeabi_idiv)
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ciENTRY(__modsi3)
3088c2ecf20Sopenharmony_ciUNWIND(.fnstart)
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	cmp	r1, #0
3118c2ecf20Sopenharmony_ci	beq	Ldiv0
3128c2ecf20Sopenharmony_ci	rsbmi	r1, r1, #0			@ loops below use unsigned.
3138c2ecf20Sopenharmony_ci	movs	ip, r0				@ preserve sign of dividend
3148c2ecf20Sopenharmony_ci	rsbmi	r0, r0, #0			@ if negative make positive
3158c2ecf20Sopenharmony_ci	subs	r2, r1, #1			@ compare divisor with 1
3168c2ecf20Sopenharmony_ci	cmpne	r0, r1				@ compare dividend with divisor
3178c2ecf20Sopenharmony_ci	moveq	r0, #0
3188c2ecf20Sopenharmony_ci	tsthi	r1, r2				@ see if divisor is power of 2
3198c2ecf20Sopenharmony_ci	andeq	r0, r0, r2
3208c2ecf20Sopenharmony_ci	bls	10f
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	ARM_MOD_BODY r0, r1, r2, r3
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci10:	cmp	ip, #0
3258c2ecf20Sopenharmony_ci	rsbmi	r0, r0, #0
3268c2ecf20Sopenharmony_ci	ret	lr
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ciUNWIND(.fnend)
3298c2ecf20Sopenharmony_ciENDPROC(__modsi3)
3308c2ecf20Sopenharmony_ci
3318c2ecf20Sopenharmony_ci#ifdef CONFIG_AEABI
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ciENTRY(__aeabi_uidivmod)
3348c2ecf20Sopenharmony_ciUNWIND(.fnstart)
3358c2ecf20Sopenharmony_ciUNWIND(.save {r0, r1, ip, lr}	)
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci	stmfd	sp!, {r0, r1, ip, lr}
3388c2ecf20Sopenharmony_ci	bl	__aeabi_uidiv
3398c2ecf20Sopenharmony_ci	ldmfd	sp!, {r1, r2, ip, lr}
3408c2ecf20Sopenharmony_ci	mul	r3, r0, r2
3418c2ecf20Sopenharmony_ci	sub	r1, r1, r3
3428c2ecf20Sopenharmony_ci	ret	lr
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ciUNWIND(.fnend)
3458c2ecf20Sopenharmony_ciENDPROC(__aeabi_uidivmod)
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ciENTRY(__aeabi_idivmod)
3488c2ecf20Sopenharmony_ciUNWIND(.fnstart)
3498c2ecf20Sopenharmony_ciUNWIND(.save {r0, r1, ip, lr}	)
3508c2ecf20Sopenharmony_ci	stmfd	sp!, {r0, r1, ip, lr}
3518c2ecf20Sopenharmony_ci	bl	__aeabi_idiv
3528c2ecf20Sopenharmony_ci	ldmfd	sp!, {r1, r2, ip, lr}
3538c2ecf20Sopenharmony_ci	mul	r3, r0, r2
3548c2ecf20Sopenharmony_ci	sub	r1, r1, r3
3558c2ecf20Sopenharmony_ci	ret	lr
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ciUNWIND(.fnend)
3588c2ecf20Sopenharmony_ciENDPROC(__aeabi_idivmod)
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_ci#endif
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ciLdiv0:
3638c2ecf20Sopenharmony_ciUNWIND(.fnstart)
3648c2ecf20Sopenharmony_ciUNWIND(.pad #4)
3658c2ecf20Sopenharmony_ciUNWIND(.save {lr})
3668c2ecf20Sopenharmony_ci	str	lr, [sp, #-8]!
3678c2ecf20Sopenharmony_ci	bl	__div0
3688c2ecf20Sopenharmony_ci	mov	r0, #0			@ About as wrong as it could be.
3698c2ecf20Sopenharmony_ci	ldr	pc, [sp], #8
3708c2ecf20Sopenharmony_ciUNWIND(.fnend)
3718c2ecf20Sopenharmony_ciENDPROC(Ldiv0)
372