xref: /netbsd-src/common/lib/libc/arch/arm/quad/__aeabi_ldivmod.S (revision 353aedd819869454a2578bf38a0cf08fe7312f73)
1c5be3356Smatt/*-
2c5be3356Smatt * Copyright (c) 2012 The NetBSD Foundation, Inc.
3c5be3356Smatt * All rights reserved.
4c5be3356Smatt *
5c5be3356Smatt * This code is derived from software contributed to The NetBSD Foundation
6c5be3356Smatt * by Matt Thomas of 3am Software Foundry.
7c5be3356Smatt *
8c5be3356Smatt * Redistribution and use in source and binary forms, with or without
9c5be3356Smatt * modification, are permitted provided that the following conditions
10c5be3356Smatt * are met:
11c5be3356Smatt * 1. Redistributions of source code must retain the above copyright
12c5be3356Smatt *    notice, this list of conditions and the following disclaimer.
13c5be3356Smatt * 2. Redistributions in binary form must reproduce the above copyright
14c5be3356Smatt *    notice, this list of conditions and the following disclaimer in the
15c5be3356Smatt *    documentation and/or other materials provided with the distribution.
16c5be3356Smatt *
17c5be3356Smatt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18c5be3356Smatt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19c5be3356Smatt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20c5be3356Smatt * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21c5be3356Smatt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22c5be3356Smatt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23c5be3356Smatt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24c5be3356Smatt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25c5be3356Smatt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26c5be3356Smatt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27c5be3356Smatt * POSSIBILITY OF SUCH DAMAGE.
28c5be3356Smatt */
29c5be3356Smatt
30c5be3356Smatt#include <machine/asm.h>
31c5be3356Smatt
32*353aedd8SjoergRCSID("$NetBSD: __aeabi_ldivmod.S,v 1.13 2014/05/06 16:02:11 joerg Exp $")
33c5be3356Smatt
34c5be3356Smatt#ifdef __ARMEB__
35c5be3356Smatt#define	ALO	r1	/* incoming numerator, outgoing quotient */
36c5be3356Smatt#define	AHI	r0	/* incoming numerator, outgoing quotient */
37c5be3356Smatt#define	BLO	r3	/* incoming denominator, outgoing remainder */
38c5be3356Smatt#define	BHI	r2	/* incoming denominator, outgoing remainder */
39c5be3356Smatt#else
40c5be3356Smatt#define	ALO	r0	/* incoming numerator, outgoing quotient */
41c5be3356Smatt#define	AHI	r1	/* incoming numerator, outgoing quotient */
42c5be3356Smatt#define	BLO	r2	/* incoming denominator, outgoing remainder */
43c5be3356Smatt#define	BHI	r3	/* incoming denominator, outgoing remainder */
44c5be3356Smatt#endif
45c5be3356Smatt
46eeddcf15SmattENTRY(__aeabi_ldivmod)
47eeddcf15Smatt#ifdef __ARM_EABI__
48*353aedd8Sjoerg# if !defined(__ARM_DWARF_EH__)
49eeddcf15Smatt	.fnstart
50*353aedd8Sjoerg# endif
51eeddcf15Smatt	.cfi_startproc
52eeddcf15Smatt#endif
53eeddcf15Smatt#if !defined(_KERNEL) && !defined(_STANDALONE)
54eeddcf15Smatt#if !defined(__thumb__)
55eeddcf15Smatt	orrs	ip, BLO, BHI
56eeddcf15Smatt	beq	.Ldivbyzero
57eeddcf15Smatt#elif defined(_ARM_ARCH_T2)
58eeddcf15Smatt	cbnz	BLO, 1f
59eeddcf15Smatt	cbz	BHI, .Ldivbyzero
60eeddcf15Smatt#else
61eeddcf15Smatt	cmp	BLO, #0
62eeddcf15Smatt	bne	1f
63eeddcf15Smatt	cmp	BHI, #0
64eeddcf15Smatt	beq	.Ldivbyzero
65eeddcf15Smatt#endif
66eeddcf15Smatt1:
67eeddcf15Smatt#endif
68eeddcf15Smatt
69eeddcf15Smatt	push	{r4-r6, lr}
70eeddcf15Smatt#ifdef __ARM_EABI__
71eeddcf15Smatt	.cfi_def_cfa_offset 16
72eeddcf15Smatt	.cfi_offset 14, -4
73eeddcf15Smatt	.cfi_offset 6, -8
74eeddcf15Smatt	.cfi_offset 5, -12
75eeddcf15Smatt	.cfi_offset 4, -16
76eeddcf15Smatt#endif
77eeddcf15Smatt#define	NEG	r5
78eeddcf15Smatt	movs	NEG, #0
79eeddcf15Smatt
80c5be3356Smatt	cmp	BHI, #0
81c5be3356Smatt	bge	2f
82eeddcf15Smatt	movs	NEG, #1		/* flip quotient sign */
83c5be3356Smatt	bl	.Lnegate_b
84c5be3356Smatt	bcs	.Lmaxdenom
85c5be3356Smatt
86c5be3356Smatt2:
87c5be3356Smatt	cmp	AHI, #0
88eeddcf15Smatt#ifdef __thumb__
89eeddcf15Smatt	bge	3f
90eeddcf15Smatt	movs	r4, #3
91eeddcf15Smatt	eors	NEG, NEG, r4	/* flip quotient sign, flip remainder sign */
92eeddcf15Smatt	bl	.Lnegate_a
93eeddcf15Smatt3:
94eeddcf15Smatt#else
95c5be3356Smatt	eorlt	NEG, NEG, #3	/* flip quotient sign, flip remainder sign */
96c5be3356Smatt	bllt	.Lnegate_a
97eeddcf15Smatt#endif
98eeddcf15Smatt
99c5be3356Smatt	/*
100c5be3356Smatt	 * Arguments are setup, allocate some stack for the remainder
101c5be3356Smatt	 * and call __qdivrem for the heavy lifting.
102c5be3356Smatt	 */
103eeddcf15Smatt#ifdef __ARM_EABI__
104eeddcf15Smatt	.cfi_def_cfa_offset 32
105eeddcf15Smatt#endif
10604413935Smatt	sub	sp, sp, #16
107eeddcf15Smatt#if !defined(__thumb__) || defined(_ARM_ARCH_T2)
108eeddcf15Smatt	adds	r4, sp, #8
109eeddcf15Smatt#else
110eeddcf15Smatt	mov	r4, sp
111eeddcf15Smatt	adds	r4, r4, #8
112eeddcf15Smatt#endif
113eeddcf15Smatt	str	r4, [sp]
114c5be3356Smatt	bl	PLT_SYM(__qdivrem)
11504413935Smatt	add	sp, sp, #8
116eeddcf15Smatt#ifdef __ARM_EABI__
117eeddcf15Smatt	.cfi_def_cfa_offset 24
118eeddcf15Smatt	.cfi_offset 3, -20
119eeddcf15Smatt	.cfi_offset 2, -24
120eeddcf15Smatt#endif
121c5be3356Smatt
122c5be3356Smatt	/*
123c5be3356Smatt	 * The quotient is already in the right place and neither value
124c5be3356Smatt	 * needs its sign flipped.
125c5be3356Smatt	 */
126eeddcf15Smatt#if defined(__thumb__) && defined(_ARM_ARCH_T2)
127eeddcf15Smatt	cbz	NEG, .Lnegate_neither
128eeddcf15Smatt#else
129eeddcf15Smatt	cmp	NEG, #0		/* any signs to flip? */
130eeddcf15Smatt	beq	.Lnegate_neither
131eeddcf15Smatt#endif
132c5be3356Smatt
133eeddcf15Smatt	cmp	NEG, #2		/* does remainder need to be negative? */
134eeddcf15Smatt	beq	.Lnegate_b_only	/* 2 means b only */
135eeddcf15Smatt	bgt	.Lnegate_both	/* 3 means both */
136eeddcf15Smatt.Lnegate_a_only:
137eeddcf15Smatt	bl	.Lnegate_a	/* 1 means a only */
138eeddcf15Smatt.Lnegate_neither:
139eeddcf15Smatt	pop	{r2-r6, pc}	/* grab b from stack */
140eeddcf15Smatt.Lnegate_both:
141eeddcf15Smatt	bl	.Lnegate_a
142eeddcf15Smatt.Lnegate_b_only:
143eeddcf15Smatt	pop	{r2-r3}		/* get remainder */
144eeddcf15Smatt#ifdef __ARM_EABI__
145eeddcf15Smatt	.cfi_def_cfa_offset 16
146eeddcf15Smatt#endif
147eeddcf15Smatt	bl	.Lnegate_b	/* negate it */
148eeddcf15Smatt	pop	{r4-r6, pc}
149c5be3356Smatt
150eeddcf15Smatt	.align	0
151c5be3356Smatt.Lnegate_a:
152eeddcf15Smatt#ifdef __thumb__
153eeddcf15Smatt	movs	r4, AHI
154eeddcf15Smatt	movs	AHI, #0
155eeddcf15Smatt	negs	ALO, ALO
156eeddcf15Smatt	sbcs	AHI, AHI, r4
157eeddcf15Smatt#else
158eeddcf15Smatt	negs	ALO, ALO
159c5be3356Smatt	rsc	AHI, AHI, #0
160eeddcf15Smatt#endif
161c5be3356Smatt	RET
162c5be3356Smatt
163eeddcf15Smatt	.align	0
164c5be3356Smatt.Lnegate_b:
165eeddcf15Smatt#ifdef __thumb__
166eeddcf15Smatt	movs	r4, BHI
167eeddcf15Smatt	movs	BHI, #0
168eeddcf15Smatt	negs	BLO, BLO
169eeddcf15Smatt	sbcs	BHI, BHI, r4
170eeddcf15Smatt#else
171eeddcf15Smatt	negs	BLO, BLO
172c5be3356Smatt	rsc	BHI, BHI, #0
173eeddcf15Smatt#endif
174c5be3356Smatt	RET
175c5be3356Smatt
176eeddcf15Smatt	.align	0
177c5be3356Smatt.Lmaxdenom:
178c5be3356Smatt	/*
179c5be3356Smatt	 * We had a carry so the denominator must have INT64_MIN
180c5be3356Smatt	 * Also BLO and BHI never changed values so we can use
181c5be3356Smatt	 * them to see if the numerator has the same value.  We
182c5be3356Smatt	 * don't have to worry about sign.
183c5be3356Smatt	 */
184eeddcf15Smatt	cmp	BHI, AHI
185eeddcf15Smatt#ifdef __thumb__
186eeddcf15Smatt	bne	1f
187eeddcf15Smatt	cmp	BLO, ALO
188eeddcf15Smatt#else
189eeddcf15Smatt	cmpeq	BLO, ALO
190eeddcf15Smatt#endif
191c5be3356Smatt	bne	1f
192c5be3356Smatt
193c5be3356Smatt	/*
194c5be3356Smatt	 * They were equal, so we return a quotient of 1 and remainder of 0.
195c5be3356Smatt	 */
196eeddcf15Smatt	movs	ALO, #1
197eeddcf15Smatt	movs	AHI, #0
198eeddcf15Smatt	movs	BLO, #0
199eeddcf15Smatt	movs	BHI, #0
200eeddcf15Smatt	pop	{r4-r6, pc}
201c5be3356Smatt
202c5be3356Smatt	/*
203c5be3356Smatt	 * Our remainder must be the numerator and our quotient is 0.
204c5be3356Smatt	 */
205eeddcf15Smatt	.align	0
206eeddcf15Smatt1:	movs	BLO, ALO
207eeddcf15Smatt	movs	BHI, AHI
208eeddcf15Smatt	movs	ALO, #0
209eeddcf15Smatt	movs	AHI, #0
210eeddcf15Smatt	pop	{r4-r6, pc}
2118ef5fb1fSmatt
212d1e50f81Smatt#if !defined(_KERNEL) && !defined(_STANDALONE)
213eeddcf15Smatt	.align	0
2148ef5fb1fSmatt.Ldivbyzero:
215eeddcf15Smatt	push	{r0-r1,r4,lr}
216eeddcf15Smatt#ifdef __ARM_EABI__
217*353aedd8Sjoerg# if !defined(__ARM_DWARF_EH__)
218eeddcf15Smatt	.save	{r0-r1,r4,lr}
219*353aedd8Sjoerg# endif
220eeddcf15Smatt	.cfi_def_cfa_offset 16
221eeddcf15Smatt	.cfi_offset 14, -4
222eeddcf15Smatt	.cfi_offset  4, -8
223eeddcf15Smatt#endif
2246fec0397Sskrll	cmp	AHI, #0
225eeddcf15Smatt#if !defined(__thumb__) || defined(_ARM_ARCH_T2)
226eeddcf15Smatt#ifdef __thumb__
227eeddcf15Smatt	ittee	ge
228eeddcf15Smatt#endif
2298ef5fb1fSmatt	mvnge	ALO, #0
230eeddcf15Smatt	mvnge	AHI, #0x80000000
2318ef5fb1fSmatt	movlt	ALO, #0
2321271d298Smatt	movlt	AHI, #0x80000000
233eeddcf15Smatt#else
234eeddcf15Smatt	blt	1f
235eeddcf15Smatt	movs	ALO, #0
236eeddcf15Smatt	mvns	ALO, ALO
237eeddcf15Smatt	mov	AHI, ALO
238eeddcf15Smatt	lsrs	AHI, AHI, #1
239eeddcf15Smatt	b	2f
240eeddcf15Smatt1:
241eeddcf15Smatt	movs	ALO, #0
242eeddcf15Smatt	movs	AHI, #1
243eeddcf15Smatt	lsls	AHI, AHI, #31
244eeddcf15Smatt2:
245eeddcf15Smatt#endif /* __thumb__ && !_ARM_ARCH_T2 */
2468ef5fb1fSmatt	bl	PLT_SYM(__aeabi_ldiv0)
247eeddcf15Smatt	pop	{r2-r4, pc}
248eeddcf15Smatt#endif	/* !_KERNEL && !_STANDALONE */
249eeddcf15Smatt#ifdef __ARM_EABI__
250eeddcf15Smatt	.cfi_endproc
251*353aedd8Sjoerg# if !defined(__ARM_DWARF_EH__)
252eeddcf15Smatt	.fnend
253d1e50f81Smatt# endif
254*353aedd8Sjoerg#endif
255c5be3356SmattEND(__aeabi_ldivmod)
256