xref: /openbsd-src/sys/lib/libkern/arch/arm/__aeabi_ldivmod.S (revision a33d4b18e9c06c133991074ecd6f5c09abc13a4a)
1*a33d4b18Skettenis/*-
2*a33d4b18Skettenis * Copyright (c) 2012 The NetBSD Foundation, Inc.
3*a33d4b18Skettenis * All rights reserved.
4*a33d4b18Skettenis *
5*a33d4b18Skettenis * This code is derived from software contributed to The NetBSD Foundation
6*a33d4b18Skettenis * by Matt Thomas of 3am Software Foundry.
7*a33d4b18Skettenis *
8*a33d4b18Skettenis * Redistribution and use in source and binary forms, with or without
9*a33d4b18Skettenis * modification, are permitted provided that the following conditions
10*a33d4b18Skettenis * are met:
11*a33d4b18Skettenis * 1. Redistributions of source code must retain the above copyright
12*a33d4b18Skettenis *    notice, this list of conditions and the following disclaimer.
13*a33d4b18Skettenis * 2. Redistributions in binary form must reproduce the above copyright
14*a33d4b18Skettenis *    notice, this list of conditions and the following disclaimer in the
15*a33d4b18Skettenis *    documentation and/or other materials provided with the distribution.
16*a33d4b18Skettenis *
17*a33d4b18Skettenis * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18*a33d4b18Skettenis * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19*a33d4b18Skettenis * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20*a33d4b18Skettenis * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21*a33d4b18Skettenis * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22*a33d4b18Skettenis * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23*a33d4b18Skettenis * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24*a33d4b18Skettenis * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25*a33d4b18Skettenis * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26*a33d4b18Skettenis * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27*a33d4b18Skettenis * POSSIBILITY OF SUCH DAMAGE.
28*a33d4b18Skettenis */
29*a33d4b18Skettenis
30*a33d4b18Skettenis#include <machine/asm.h>
31*a33d4b18Skettenis
32*a33d4b18Skettenis#ifdef __ARMEB__
33*a33d4b18Skettenis#define	ALO	r1	/* incoming numerator, outgoing quotient */
34*a33d4b18Skettenis#define	AHI	r0	/* incoming numerator, outgoing quotient */
35*a33d4b18Skettenis#define	BLO	r3	/* incoming denominator, outgoing remainder */
36*a33d4b18Skettenis#define	BHI	r2	/* incoming denominator, outgoing remainder */
37*a33d4b18Skettenis#else
38*a33d4b18Skettenis#define	ALO	r0	/* incoming numerator, outgoing quotient */
39*a33d4b18Skettenis#define	AHI	r1	/* incoming numerator, outgoing quotient */
40*a33d4b18Skettenis#define	BLO	r2	/* incoming denominator, outgoing remainder */
41*a33d4b18Skettenis#define	BHI	r3	/* incoming denominator, outgoing remainder */
42*a33d4b18Skettenis#endif
43*a33d4b18Skettenis
44*a33d4b18SkettenisENTRY(__aeabi_ldivmod)
45*a33d4b18Skettenis	push	{r4-r6, lr}
46*a33d4b18Skettenis#define	NEG	r5
47*a33d4b18Skettenis	movs	NEG, #0
48*a33d4b18Skettenis
49*a33d4b18Skettenis	cmp	BHI, #0
50*a33d4b18Skettenis	bge	2f
51*a33d4b18Skettenis	movs	NEG, #1		/* flip quotient sign */
52*a33d4b18Skettenis	bl	.Lnegate_b
53*a33d4b18Skettenis	bcs	.Lmaxdenom
54*a33d4b18Skettenis
55*a33d4b18Skettenis2:
56*a33d4b18Skettenis	cmp	AHI, #0
57*a33d4b18Skettenis	eorlt	NEG, NEG, #3	/* flip quotient sign, flip remainder sign */
58*a33d4b18Skettenis	bllt	.Lnegate_a
59*a33d4b18Skettenis
60*a33d4b18Skettenis	/*
61*a33d4b18Skettenis	 * Arguments are setup, allocate some stack for the remainder
62*a33d4b18Skettenis	 * and call __qdivrem for the heavy lifting.
63*a33d4b18Skettenis	 */
64*a33d4b18Skettenis	sub	sp, sp, #16
65*a33d4b18Skettenis	adds	r4, sp, #8
66*a33d4b18Skettenis	str	r4, [sp]
67*a33d4b18Skettenis	bl	__qdivrem
68*a33d4b18Skettenis	add	sp, sp, #8
69*a33d4b18Skettenis
70*a33d4b18Skettenis	/*
71*a33d4b18Skettenis	 * The quotient is already in the right place and neither value
72*a33d4b18Skettenis	 * needs its sign flipped.
73*a33d4b18Skettenis	 */
74*a33d4b18Skettenis	cmp	NEG, #0		/* any signs to flip? */
75*a33d4b18Skettenis	beq	.Lnegate_neither
76*a33d4b18Skettenis
77*a33d4b18Skettenis	cmp	NEG, #2		/* does remainder need to be negative? */
78*a33d4b18Skettenis	beq	.Lnegate_b_only	/* 2 means b only */
79*a33d4b18Skettenis	bgt	.Lnegate_both	/* 3 means both */
80*a33d4b18Skettenis.Lnegate_a_only:
81*a33d4b18Skettenis	bl	.Lnegate_a	/* 1 means a only */
82*a33d4b18Skettenis.Lnegate_neither:
83*a33d4b18Skettenis	pop	{r2-r6, pc}	/* grab b from stack */
84*a33d4b18Skettenis.Lnegate_both:
85*a33d4b18Skettenis	bl	.Lnegate_a
86*a33d4b18Skettenis.Lnegate_b_only:
87*a33d4b18Skettenis	pop	{r2-r3}		/* get remainder */
88*a33d4b18Skettenis	bl	.Lnegate_b	/* negate it */
89*a33d4b18Skettenis	pop	{r4-r6, pc}
90*a33d4b18Skettenis
91*a33d4b18Skettenis	.align	0
92*a33d4b18Skettenis.Lnegate_a:
93*a33d4b18Skettenis	negs	ALO, ALO
94*a33d4b18Skettenis	rsc	AHI, AHI, #0
95*a33d4b18Skettenis	mov	pc, lr
96*a33d4b18Skettenis
97*a33d4b18Skettenis	.align	0
98*a33d4b18Skettenis.Lnegate_b:
99*a33d4b18Skettenis	negs	BLO, BLO
100*a33d4b18Skettenis	rsc	BHI, BHI, #0
101*a33d4b18Skettenis	mov	pc, lr
102*a33d4b18Skettenis
103*a33d4b18Skettenis	.align	0
104*a33d4b18Skettenis.Lmaxdenom:
105*a33d4b18Skettenis	/*
106*a33d4b18Skettenis	 * We had a carry so the denominator must have INT64_MIN
107*a33d4b18Skettenis	 * Also BLO and BHI never changed values so we can use
108*a33d4b18Skettenis	 * them to see if the numerator has the same value.  We
109*a33d4b18Skettenis	 * don't have to worry about sign.
110*a33d4b18Skettenis	 */
111*a33d4b18Skettenis	cmp	BHI, AHI
112*a33d4b18Skettenis	cmpeq	BLO, ALO
113*a33d4b18Skettenis	bne	1f
114*a33d4b18Skettenis
115*a33d4b18Skettenis	/*
116*a33d4b18Skettenis	 * They were equal, so we return a quotient of 1 and remainder of 0.
117*a33d4b18Skettenis	 */
118*a33d4b18Skettenis	movs	ALO, #1
119*a33d4b18Skettenis	movs	AHI, #0
120*a33d4b18Skettenis	movs	BLO, #0
121*a33d4b18Skettenis	movs	BHI, #0
122*a33d4b18Skettenis	pop	{r4-r6, pc}
123*a33d4b18Skettenis
124*a33d4b18Skettenis	/*
125*a33d4b18Skettenis	 * Our remainder must be the numerator and our quotient is 0.
126*a33d4b18Skettenis	 */
127*a33d4b18Skettenis	.align	0
128*a33d4b18Skettenis1:	movs	BLO, ALO
129*a33d4b18Skettenis	movs	BHI, AHI
130*a33d4b18Skettenis	movs	ALO, #0
131*a33d4b18Skettenis	movs	AHI, #0
132*a33d4b18Skettenis	pop	{r4-r6, pc}
133*a33d4b18SkettenisEND(__aeabi_ldivmod)
134