divsi3.S revision 129202
187866Ssheldonh/*	$NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $	*/
287866Ssheldonh
387866Ssheldonh/*
487866Ssheldonh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
587866Ssheldonh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
687866Ssheldonh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
787866Ssheldonh * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
887866Ssheldonh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
987866Ssheldonh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
1087866Ssheldonh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
1187866Ssheldonh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1287866Ssheldonh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1387866Ssheldonh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
1487866Ssheldonh * SUCH DAMAGE.
1587866Ssheldonh */
1687866Ssheldonh
1787866Ssheldonh#include <machine/asm.h>
1887866Ssheldonh__FBSDID("$FreeBSD: head/lib/libc/arm/gen/divsi3.S 129202 2004-05-14 12:04:31Z cognet $");
1987866Ssheldonh
2087866Ssheldonh/*
2187866Ssheldonh * stack is aligned as there's a possibility of branching to L_overflow
2287866Ssheldonh * which makes a C call
2387866Ssheldonh */
2487866Ssheldonh
2587866SsheldonhENTRY(__umodsi3)
2687866Ssheldonh	stmfd	sp!, {lr}
2787866Ssheldonh	sub	sp, sp, #4	/* align stack */
2887866Ssheldonh	bl	.L_udivide
2987866Ssheldonh	add	sp, sp, #4	/* unalign stack */
3087866Ssheldonh	mov	r0, r1
3187866Ssheldonh	ldmfd	sp!, {pc}
3287866Ssheldonh
3387866SsheldonhENTRY(__modsi3)
34136700Sobrien	stmfd	sp!, {lr}
35136700Sobrien	sub	sp, sp, #4	/* align stack */
36136700Sobrien	bl	.L_divide
37136700Sobrien	add	sp, sp, #4	/* unalign stack */
3887866Ssheldonh	mov	r0, r1
3987866Ssheldonh	ldmfd	sp!, {pc}
4087866Ssheldonh
4187866Ssheldonh.L_overflow:
4287866Ssheldonh#if !defined(_KERNEL) && !defined(_STANDALONE)
4387866Ssheldonh	mov	r0, #8			/* SIGFPE */
4487866Ssheldonh	bl	PIC_SYM(_C_LABEL(raise), PLT)	/* raise it */
4587866Ssheldonh	mov	r0, #0
4687866Ssheldonh#else
4787866Ssheldonh	/* XXX should cause a fatal error */
4887866Ssheldonh	mvn	r0, #0
4987866Ssheldonh#endif
5087866Ssheldonh	mov	pc, lr
5187866Ssheldonh
5287866SsheldonhENTRY(__udivsi3)
5387866Ssheldonh.L_udivide:				/* r0 = r0 / r1; r1 = r0 % r1 */
5487866Ssheldonh	eor     r0, r1, r0
5587866Ssheldonh	eor     r1, r0, r1
5687866Ssheldonh	eor     r0, r1, r0
5787866Ssheldonh					/* r0 = r1 / r0; r1 = r1 % r0 */
5887866Ssheldonh	cmp	r0, #1
5987866Ssheldonh	bcc	.L_overflow
6087866Ssheldonh	beq	.L_divide_l0
6187866Ssheldonh	mov	ip, #0
6287866Ssheldonh	movs	r1, r1
6387866Ssheldonh	bpl	.L_divide_l1
6487866Ssheldonh	orr	ip, ip, #0x20000000	/* ip bit 0x20000000 = -ve r1 */
6587866Ssheldonh	movs	r1, r1, lsr #1
6687866Ssheldonh	orrcs	ip, ip, #0x10000000	/* ip bit 0x10000000 = bit 0 of r1 */
6787866Ssheldonh	b	.L_divide_l1
6887866Ssheldonh
6987866Ssheldonh.L_divide_l0:				/* r0 == 1 */
7087866Ssheldonh	mov	r0, r1
7187866Ssheldonh	mov	r1, #0
7287866Ssheldonh	mov	pc, lr
7387866Ssheldonh
7487866SsheldonhENTRY(__divsi3)
7587866Ssheldonh.L_divide:				/* r0 = r0 / r1; r1 = r0 % r1 */
7687866Ssheldonh	eor     r0, r1, r0
7787866Ssheldonh	eor     r1, r0, r1
7887866Ssheldonh	eor     r0, r1, r0
7987866Ssheldonh					/* r0 = r1 / r0; r1 = r1 % r0 */
8087866Ssheldonh	cmp	r0, #1
8187866Ssheldonh	bcc	.L_overflow
8287866Ssheldonh	beq	.L_divide_l0
8387866Ssheldonh	ands	ip, r0, #0x80000000
8487866Ssheldonh	rsbmi	r0, r0, #0
8587866Ssheldonh	ands	r2, r1, #0x80000000
8687866Ssheldonh	eor	ip, ip, r2
8787866Ssheldonh	rsbmi	r1, r1, #0
8887866Ssheldonh	orr	ip, r2, ip, lsr #1	/* ip bit 0x40000000 = -ve division */
8987866Ssheldonh					/* ip bit 0x80000000 = -ve remainder */
9087866Ssheldonh
9187866Ssheldonh.L_divide_l1:
9287866Ssheldonh	mov	r2, #1
9387866Ssheldonh	mov	r3, #0
9487866Ssheldonh
9587866Ssheldonh	/*
9687866Ssheldonh	 * If the highest bit of the dividend is set, we have to be
9787866Ssheldonh	 * careful when shifting the divisor. Test this.
9887866Ssheldonh	 */
9987866Ssheldonh	movs	r1,r1
10087866Ssheldonh	bpl	.L_old_code
10187866Ssheldonh
10287866Ssheldonh	/*
10387866Ssheldonh	 * At this point, the highest bit of r1 is known to be set.
10487866Ssheldonh	 * We abuse this below in the tst instructions.
10587866Ssheldonh	 */
10687866Ssheldonh	tst	r1, r0 /*, lsl #0 */
10787866Ssheldonh	bmi	.L_divide_b1
10887866Ssheldonh	tst	r1, r0, lsl #1
10987866Ssheldonh	bmi	.L_divide_b2
11087866Ssheldonh	tst	r1, r0, lsl #2
11187866Ssheldonh	bmi	.L_divide_b3
11287866Ssheldonh	tst	r1, r0, lsl #3
11387866Ssheldonh	bmi	.L_divide_b4
11487866Ssheldonh	tst	r1, r0, lsl #4
11587866Ssheldonh	bmi	.L_divide_b5
11687866Ssheldonh	tst	r1, r0, lsl #5
11787866Ssheldonh	bmi	.L_divide_b6
11887866Ssheldonh	tst	r1, r0, lsl #6
11987866Ssheldonh	bmi	.L_divide_b7
12087866Ssheldonh	tst	r1, r0, lsl #7
12187866Ssheldonh	bmi	.L_divide_b8
12287866Ssheldonh	tst	r1, r0, lsl #8
12387866Ssheldonh	bmi	.L_divide_b9
12487866Ssheldonh	tst	r1, r0, lsl #9
12587866Ssheldonh	bmi	.L_divide_b10
12687866Ssheldonh	tst	r1, r0, lsl #10
12787866Ssheldonh	bmi	.L_divide_b11
12887866Ssheldonh	tst	r1, r0, lsl #11
12987866Ssheldonh	bmi	.L_divide_b12
13087866Ssheldonh	tst	r1, r0, lsl #12
13187866Ssheldonh	bmi	.L_divide_b13
13287866Ssheldonh	tst	r1, r0, lsl #13
13387866Ssheldonh	bmi	.L_divide_b14
13487866Ssheldonh	tst	r1, r0, lsl #14
13587866Ssheldonh	bmi	.L_divide_b15
13687866Ssheldonh	tst	r1, r0, lsl #15
13787866Ssheldonh	bmi	.L_divide_b16
13887866Ssheldonh	tst	r1, r0, lsl #16
13987866Ssheldonh	bmi	.L_divide_b17
14087866Ssheldonh	tst	r1, r0, lsl #17
14187866Ssheldonh	bmi	.L_divide_b18
14287866Ssheldonh	tst	r1, r0, lsl #18
14387866Ssheldonh	bmi	.L_divide_b19
14487866Ssheldonh	tst	r1, r0, lsl #19
14587866Ssheldonh	bmi	.L_divide_b20
14687866Ssheldonh	tst	r1, r0, lsl #20
14787866Ssheldonh	bmi	.L_divide_b21
14887866Ssheldonh	tst	r1, r0, lsl #21
14987866Ssheldonh	bmi	.L_divide_b22
15087866Ssheldonh	tst	r1, r0, lsl #22
15187866Ssheldonh	bmi	.L_divide_b23
15287866Ssheldonh	tst	r1, r0, lsl #23
15387866Ssheldonh	bmi	.L_divide_b24
15487866Ssheldonh	tst	r1, r0, lsl #24
15587866Ssheldonh	bmi	.L_divide_b25
15687866Ssheldonh	tst	r1, r0, lsl #25
15787866Ssheldonh	bmi	.L_divide_b26
15887866Ssheldonh	tst	r1, r0, lsl #26
15987866Ssheldonh	bmi	.L_divide_b27
16087866Ssheldonh	tst	r1, r0, lsl #27
16187866Ssheldonh	bmi	.L_divide_b28
16287866Ssheldonh	tst	r1, r0, lsl #28
16387866Ssheldonh	bmi	.L_divide_b29
16487866Ssheldonh	tst	r1, r0, lsl #29
16587866Ssheldonh	bmi	.L_divide_b30
16687866Ssheldonh	tst	r1, r0, lsl #30
16787866Ssheldonh	bmi	.L_divide_b31
16887866Ssheldonh/*
16987866Ssheldonh * instead of:
17087866Ssheldonh *	tst	r1, r0, lsl #31
17187866Ssheldonh *	bmi	.L_divide_b32
17287866Ssheldonh */
17387866Ssheldonh	b	.L_divide_b32
17487866Ssheldonh
17587866Ssheldonh.L_old_code:
17687866Ssheldonh	cmp	r1, r0
17787866Ssheldonh	bcc	.L_divide_b0
17887866Ssheldonh	cmp	r1, r0, lsl #1
17987866Ssheldonh	bcc	.L_divide_b1
18087866Ssheldonh	cmp	r1, r0, lsl #2
18187866Ssheldonh	bcc	.L_divide_b2
18287866Ssheldonh	cmp	r1, r0, lsl #3
18387866Ssheldonh	bcc	.L_divide_b3
18487866Ssheldonh	cmp	r1, r0, lsl #4
18587866Ssheldonh	bcc	.L_divide_b4
18687866Ssheldonh	cmp	r1, r0, lsl #5
18787866Ssheldonh	bcc	.L_divide_b5
18887866Ssheldonh	cmp	r1, r0, lsl #6
18987866Ssheldonh	bcc	.L_divide_b6
19087866Ssheldonh	cmp	r1, r0, lsl #7
19187866Ssheldonh	bcc	.L_divide_b7
19287866Ssheldonh	cmp	r1, r0, lsl #8
19387866Ssheldonh	bcc	.L_divide_b8
19487866Ssheldonh	cmp	r1, r0, lsl #9
19587866Ssheldonh	bcc	.L_divide_b9
19687866Ssheldonh	cmp	r1, r0, lsl #10
19787866Ssheldonh	bcc	.L_divide_b10
19887866Ssheldonh	cmp	r1, r0, lsl #11
19987866Ssheldonh	bcc	.L_divide_b11
20087866Ssheldonh	cmp	r1, r0, lsl #12
20187866Ssheldonh	bcc	.L_divide_b12
20287866Ssheldonh	cmp	r1, r0, lsl #13
20387866Ssheldonh	bcc	.L_divide_b13
20487866Ssheldonh	cmp	r1, r0, lsl #14
20587866Ssheldonh	bcc	.L_divide_b14
20687866Ssheldonh	cmp	r1, r0, lsl #15
20787866Ssheldonh	bcc	.L_divide_b15
20887866Ssheldonh	cmp	r1, r0, lsl #16
20987866Ssheldonh	bcc	.L_divide_b16
21087866Ssheldonh	cmp	r1, r0, lsl #17
21187866Ssheldonh	bcc	.L_divide_b17
21287866Ssheldonh	cmp	r1, r0, lsl #18
21387866Ssheldonh	bcc	.L_divide_b18
21487866Ssheldonh	cmp	r1, r0, lsl #19
21587866Ssheldonh	bcc	.L_divide_b19
21687866Ssheldonh	cmp	r1, r0, lsl #20
21787866Ssheldonh	bcc	.L_divide_b20
21887866Ssheldonh	cmp	r1, r0, lsl #21
21987866Ssheldonh	bcc	.L_divide_b21
22087866Ssheldonh	cmp	r1, r0, lsl #22
22187866Ssheldonh	bcc	.L_divide_b22
22287866Ssheldonh	cmp	r1, r0, lsl #23
22387866Ssheldonh	bcc	.L_divide_b23
22487866Ssheldonh	cmp	r1, r0, lsl #24
22587866Ssheldonh	bcc	.L_divide_b24
22687866Ssheldonh	cmp	r1, r0, lsl #25
22787866Ssheldonh	bcc	.L_divide_b25
22887866Ssheldonh	cmp	r1, r0, lsl #26
22987866Ssheldonh	bcc	.L_divide_b26
23087866Ssheldonh	cmp	r1, r0, lsl #27
23187866Ssheldonh	bcc	.L_divide_b27
23287866Ssheldonh	cmp	r1, r0, lsl #28
23387866Ssheldonh	bcc	.L_divide_b28
23487866Ssheldonh	cmp	r1, r0, lsl #29
23587866Ssheldonh	bcc	.L_divide_b29
23687866Ssheldonh	cmp	r1, r0, lsl #30
23787866Ssheldonh	bcc	.L_divide_b30
23887866Ssheldonh.L_divide_b32:
23987866Ssheldonh	cmp	r1, r0, lsl #31
24087866Ssheldonh	subhs	r1, r1,r0, lsl #31
24187866Ssheldonh	addhs	r3, r3,r2, lsl #31
24287866Ssheldonh.L_divide_b31:
24387866Ssheldonh	cmp	r1, r0, lsl #30
24487866Ssheldonh	subhs	r1, r1,r0, lsl #30
24587866Ssheldonh	addhs	r3, r3,r2, lsl #30
24687866Ssheldonh.L_divide_b30:
24787866Ssheldonh	cmp	r1, r0, lsl #29
24887866Ssheldonh	subhs	r1, r1,r0, lsl #29
24987866Ssheldonh	addhs	r3, r3,r2, lsl #29
25087866Ssheldonh.L_divide_b29:
25187866Ssheldonh	cmp	r1, r0, lsl #28
25287866Ssheldonh	subhs	r1, r1,r0, lsl #28
25387866Ssheldonh	addhs	r3, r3,r2, lsl #28
25487866Ssheldonh.L_divide_b28:
25587866Ssheldonh	cmp	r1, r0, lsl #27
25687866Ssheldonh	subhs	r1, r1,r0, lsl #27
25787866Ssheldonh	addhs	r3, r3,r2, lsl #27
25887866Ssheldonh.L_divide_b27:
25987866Ssheldonh	cmp	r1, r0, lsl #26
26087866Ssheldonh	subhs	r1, r1,r0, lsl #26
26187866Ssheldonh	addhs	r3, r3,r2, lsl #26
26287866Ssheldonh.L_divide_b26:
26387866Ssheldonh	cmp	r1, r0, lsl #25
26487866Ssheldonh	subhs	r1, r1,r0, lsl #25
26587866Ssheldonh	addhs	r3, r3,r2, lsl #25
26687866Ssheldonh.L_divide_b25:
26787866Ssheldonh	cmp	r1, r0, lsl #24
26887866Ssheldonh	subhs	r1, r1,r0, lsl #24
26987866Ssheldonh	addhs	r3, r3,r2, lsl #24
27087866Ssheldonh.L_divide_b24:
27187866Ssheldonh	cmp	r1, r0, lsl #23
27287866Ssheldonh	subhs	r1, r1,r0, lsl #23
27387866Ssheldonh	addhs	r3, r3,r2, lsl #23
27487866Ssheldonh.L_divide_b23:
27587866Ssheldonh	cmp	r1, r0, lsl #22
27687866Ssheldonh	subhs	r1, r1,r0, lsl #22
27787866Ssheldonh	addhs	r3, r3,r2, lsl #22
27887866Ssheldonh.L_divide_b22:
27987866Ssheldonh	cmp	r1, r0, lsl #21
28087866Ssheldonh	subhs	r1, r1,r0, lsl #21
28187866Ssheldonh	addhs	r3, r3,r2, lsl #21
28287866Ssheldonh.L_divide_b21:
28387866Ssheldonh	cmp	r1, r0, lsl #20
28487866Ssheldonh	subhs	r1, r1,r0, lsl #20
28587866Ssheldonh	addhs	r3, r3,r2, lsl #20
28687866Ssheldonh.L_divide_b20:
28787866Ssheldonh	cmp	r1, r0, lsl #19
28887866Ssheldonh	subhs	r1, r1,r0, lsl #19
28987866Ssheldonh	addhs	r3, r3,r2, lsl #19
29087866Ssheldonh.L_divide_b19:
29187866Ssheldonh	cmp	r1, r0, lsl #18
29287866Ssheldonh	subhs	r1, r1,r0, lsl #18
29387866Ssheldonh	addhs	r3, r3,r2, lsl #18
29487866Ssheldonh.L_divide_b18:
29587866Ssheldonh	cmp	r1, r0, lsl #17
29687866Ssheldonh	subhs	r1, r1,r0, lsl #17
29787866Ssheldonh	addhs	r3, r3,r2, lsl #17
29887866Ssheldonh.L_divide_b17:
29987866Ssheldonh	cmp	r1, r0, lsl #16
30087866Ssheldonh	subhs	r1, r1,r0, lsl #16
30187866Ssheldonh	addhs	r3, r3,r2, lsl #16
30287866Ssheldonh.L_divide_b16:
30387866Ssheldonh	cmp	r1, r0, lsl #15
30487866Ssheldonh	subhs	r1, r1,r0, lsl #15
30587866Ssheldonh	addhs	r3, r3,r2, lsl #15
30687866Ssheldonh.L_divide_b15:
30787866Ssheldonh	cmp	r1, r0, lsl #14
30887866Ssheldonh	subhs	r1, r1,r0, lsl #14
30987866Ssheldonh	addhs	r3, r3,r2, lsl #14
31087866Ssheldonh.L_divide_b14:
31187866Ssheldonh	cmp	r1, r0, lsl #13
31287866Ssheldonh	subhs	r1, r1,r0, lsl #13
31387866Ssheldonh	addhs	r3, r3,r2, lsl #13
31487866Ssheldonh.L_divide_b13:
31587866Ssheldonh	cmp	r1, r0, lsl #12
31687866Ssheldonh	subhs	r1, r1,r0, lsl #12
31787866Ssheldonh	addhs	r3, r3,r2, lsl #12
31887866Ssheldonh.L_divide_b12:
31987866Ssheldonh	cmp	r1, r0, lsl #11
32087866Ssheldonh	subhs	r1, r1,r0, lsl #11
32187866Ssheldonh	addhs	r3, r3,r2, lsl #11
32287866Ssheldonh.L_divide_b11:
32387866Ssheldonh	cmp	r1, r0, lsl #10
32487866Ssheldonh	subhs	r1, r1,r0, lsl #10
32587866Ssheldonh	addhs	r3, r3,r2, lsl #10
32687866Ssheldonh.L_divide_b10:
32787866Ssheldonh	cmp	r1, r0, lsl #9
32887866Ssheldonh	subhs	r1, r1,r0, lsl #9
32987866Ssheldonh	addhs	r3, r3,r2, lsl #9
33087866Ssheldonh.L_divide_b9:
33187866Ssheldonh	cmp	r1, r0, lsl #8
33287866Ssheldonh	subhs	r1, r1,r0, lsl #8
33387866Ssheldonh	addhs	r3, r3,r2, lsl #8
33487866Ssheldonh.L_divide_b8:
33587866Ssheldonh	cmp	r1, r0, lsl #7
33687866Ssheldonh	subhs	r1, r1,r0, lsl #7
33787866Ssheldonh	addhs	r3, r3,r2, lsl #7
33887866Ssheldonh.L_divide_b7:
33987866Ssheldonh	cmp	r1, r0, lsl #6
34087866Ssheldonh	subhs	r1, r1,r0, lsl #6
34187866Ssheldonh	addhs	r3, r3,r2, lsl #6
34287866Ssheldonh.L_divide_b6:
34387866Ssheldonh	cmp	r1, r0, lsl #5
34487866Ssheldonh	subhs	r1, r1,r0, lsl #5
34587866Ssheldonh	addhs	r3, r3,r2, lsl #5
34687866Ssheldonh.L_divide_b5:
34787866Ssheldonh	cmp	r1, r0, lsl #4
34887866Ssheldonh	subhs	r1, r1,r0, lsl #4
34987866Ssheldonh	addhs	r3, r3,r2, lsl #4
35087866Ssheldonh.L_divide_b4:
351136700Sobrien	cmp	r1, r0, lsl #3
35287866Ssheldonh	subhs	r1, r1,r0, lsl #3
35387866Ssheldonh	addhs	r3, r3,r2, lsl #3
35487866Ssheldonh.L_divide_b3:
35587866Ssheldonh	cmp	r1, r0, lsl #2
35687866Ssheldonh	subhs	r1, r1,r0, lsl #2
35787866Ssheldonh	addhs	r3, r3,r2, lsl #2
35887866Ssheldonh.L_divide_b2:
35987866Ssheldonh	cmp	r1, r0, lsl #1
36087866Ssheldonh	subhs	r1, r1,r0, lsl #1
36187866Ssheldonh	addhs	r3, r3,r2, lsl #1
36287866Ssheldonh.L_divide_b1:
36387866Ssheldonh	cmp	r1, r0
36487866Ssheldonh	subhs	r1, r1, r0
36587866Ssheldonh	addhs	r3, r3, r2
36687866Ssheldonh.L_divide_b0:
36787866Ssheldonh
36887866Ssheldonh	tst	ip, #0x20000000
36987866Ssheldonh	bne	.L_udivide_l1
37087866Ssheldonh	mov	r0, r3
37187866Ssheldonh	cmp	ip, #0
37287866Ssheldonh	rsbmi	r1, r1, #0
37387866Ssheldonh	movs	ip, ip, lsl #1
37487866Ssheldonh	bicmi	r0, r0, #0x80000000	/* Fix incase we divided 0x80000000 */
37587866Ssheldonh	rsbmi	r0, r0, #0
37687866Ssheldonh	mov	pc, lr
37787866Ssheldonh
37887866Ssheldonh.L_udivide_l1:
37987866Ssheldonh	tst	ip, #0x10000000
38087866Ssheldonh	mov	r1, r1, lsl #1
38187866Ssheldonh	orrne	r1, r1, #1
38287866Ssheldonh	mov	r3, r3, lsl #1
38387866Ssheldonh	cmp	r1, r0
38487866Ssheldonh	subhs	r1, r1, r0
38587866Ssheldonh	addhs	r3, r3, r2
38687866Ssheldonh	mov	r0, r3
38787866Ssheldonh	mov	pc, lr
38887866Ssheldonh