xref: /titanic_51/usr/src/lib/libc/i386/gen/_divdi3.s (revision 9a70fc3be3b1e966bf78825cdb8d509963a6f0a1)
10ec57554Sraf/*
20ec57554Sraf * CDDL HEADER START
30ec57554Sraf *
40ec57554Sraf * The contents of this file are subject to the terms of the
5*9a70fc3bSMark J. Nelson * Common Development and Distribution License (the "License").
6*9a70fc3bSMark J. Nelson * You may not use this file except in compliance with the License.
70ec57554Sraf *
80ec57554Sraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90ec57554Sraf * or http://www.opensolaris.org/os/licensing.
100ec57554Sraf * See the License for the specific language governing permissions
110ec57554Sraf * and limitations under the License.
120ec57554Sraf *
130ec57554Sraf * When distributing Covered Code, include this CDDL HEADER in each
140ec57554Sraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150ec57554Sraf * If applicable, add the following below this CDDL HEADER, with the
160ec57554Sraf * fields enclosed by brackets "[]" replaced with your own identifying
170ec57554Sraf * information: Portions Copyright [yyyy] [name of copyright owner]
180ec57554Sraf *
190ec57554Sraf * CDDL HEADER END
200ec57554Sraf */
210ec57554Sraf
220ec57554Sraf/*
230ec57554Sraf * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240ec57554Sraf * Use is subject to license terms.
250ec57554Sraf */
260ec57554Sraf
27*9a70fc3bSMark J. Nelson	.file	"_divdi3.s"
280ec57554Sraf
290ec57554Sraf#include <SYS.h>
300ec57554Sraf
310ec57554Sraf/*
320ec57554Sraf * C support for 64-bit modulo and division.
330ec57554Sraf * GNU routines callable from C (though generated by the compiler).
340ec57554Sraf * Hand-customized compiler output - see comments for details.
350ec57554Sraf */
360ec57554Sraf
370ec57554Sraf#if defined(__lint)
380ec57554Sraf
390ec57554Sraf/*ARGSUSED*/
400ec57554Srafuint64_t
410ec57554Sraf__udivdi3(uint64_t a, uint64_t b)
420ec57554Sraf{ return (0); }
430ec57554Sraf
440ec57554Sraf/*ARGSUSED*/
450ec57554Srafuint64_t
460ec57554Sraf__umoddi3(uint64_t a, uint64_t b)
470ec57554Sraf{ return (0); }
480ec57554Sraf
490ec57554Sraf/*ARGSUSED*/
500ec57554Srafint64_t
510ec57554Sraf__divdi3(int64_t a, int64_t b)
520ec57554Sraf{ return (0); }
530ec57554Sraf
540ec57554Sraf/*ARGSUSED*/
550ec57554Srafint64_t
560ec57554Sraf__moddi3(int64_t a, int64_t b)
570ec57554Sraf{ return (0); }
580ec57554Sraf
590ec57554Sraf#else
600ec57554Sraf
610ec57554Sraf/*
620ec57554Sraf * __udivdi3
630ec57554Sraf *
640ec57554Sraf * Perform division of two unsigned 64-bit quantities, returning the
650ec57554Sraf * quotient in %edx:%eax.
660ec57554Sraf */
670ec57554Sraf	ENTRY(__udivdi3)
680ec57554Sraf	movl	4(%esp), %eax	/ x, x
690ec57554Sraf	movl	8(%esp), %edx	/ x, x
700ec57554Sraf	pushl	16(%esp)	/ y
710ec57554Sraf	pushl	16(%esp)
720ec57554Sraf	call	UDiv
730ec57554Sraf	addl	$8, %esp
740ec57554Sraf	ret
750ec57554Sraf	SET_SIZE(__udivdi3)
760ec57554Sraf
770ec57554Sraf/*
780ec57554Sraf * __umoddi3
790ec57554Sraf *
800ec57554Sraf * Perform division of two unsigned 64-bit quantities, returning the
810ec57554Sraf * remainder in %edx:%eax.
820ec57554Sraf */
830ec57554Sraf	ENTRY(__umoddi3)
840ec57554Sraf	subl	$12, %esp
850ec57554Sraf	movl	%esp, %ecx	/, tmp65
860ec57554Sraf	movl	16(%esp), %eax	/ x, x
870ec57554Sraf	movl	20(%esp), %edx	/ x, x
880ec57554Sraf	pushl	%ecx		/ tmp65
890ec57554Sraf	pushl	32(%esp)	/ y
900ec57554Sraf	pushl	32(%esp)
910ec57554Sraf	call	UDivRem
920ec57554Sraf	movl	12(%esp), %eax	/ rem, rem
930ec57554Sraf	movl	16(%esp), %edx	/ rem, rem
940ec57554Sraf	addl	$24, %esp
950ec57554Sraf	ret
960ec57554Sraf	SET_SIZE(__umoddi3)
970ec57554Sraf
980ec57554Sraf/*
990ec57554Sraf * __divdi3
1000ec57554Sraf *
1010ec57554Sraf * Perform division of two signed 64-bit quantities, returning the
1020ec57554Sraf * quotient in %edx:%eax.
1030ec57554Sraf */
1040ec57554Sraf/ int64_t
1050ec57554Sraf/ __divdi3(int64_t x, int64_t y)
1060ec57554Sraf/ {
1070ec57554Sraf/ 	int		negative;
1080ec57554Sraf/ 	uint64_t	xt, yt, r;
1090ec57554Sraf/
1100ec57554Sraf/ 	if (x < 0) {
1110ec57554Sraf/ 		xt = -(uint64_t) x;
1120ec57554Sraf/ 		negative = 1;
1130ec57554Sraf/ 	} else {
1140ec57554Sraf/ 		xt = x;
1150ec57554Sraf/ 		negative = 0;
1160ec57554Sraf/ 	}
1170ec57554Sraf/ 	if (y < 0) {
1180ec57554Sraf/ 		yt = -(uint64_t) y;
1190ec57554Sraf/ 		negative ^= 1;
1200ec57554Sraf/ 	} else {
1210ec57554Sraf/ 		yt = y;
1220ec57554Sraf/ 	}
1230ec57554Sraf/ 	r = UDiv(xt, yt);
1240ec57554Sraf/ 	return (negative ? (int64_t) - r : r);
1250ec57554Sraf/ }
1260ec57554Sraf	ENTRY(__divdi3)
1270ec57554Sraf	pushl	%ebp
1280ec57554Sraf	pushl	%edi
1290ec57554Sraf	pushl	%esi
1300ec57554Sraf	subl	$8, %esp
1310ec57554Sraf	movl	28(%esp), %edx	/ x, x
1320ec57554Sraf	testl	%edx, %edx	/ x
1330ec57554Sraf	movl	24(%esp), %eax	/ x, x
1340ec57554Sraf	movl	32(%esp), %esi	/ y, y
1350ec57554Sraf	movl	36(%esp), %edi	/ y, y
1360ec57554Sraf	js	.LL55
1370ec57554Sraf	xorl	%ebp, %ebp	/ negative
1380ec57554Sraf	testl	%edi, %edi	/ y
1390ec57554Sraf	movl	%eax, (%esp)	/ x, xt
1400ec57554Sraf	movl	%edx, 4(%esp)	/ x, xt
1410ec57554Sraf	movl	%esi, %eax	/ y, yt
1420ec57554Sraf	movl	%edi, %edx	/ y, yt
1430ec57554Sraf	js	.LL56
1440ec57554Sraf.LL53:
1450ec57554Sraf	pushl	%edx		/ yt
1460ec57554Sraf	pushl	%eax		/ yt
1470ec57554Sraf	movl	8(%esp), %eax	/ xt, xt
1480ec57554Sraf	movl	12(%esp), %edx	/ xt, xt
1490ec57554Sraf	call	UDiv
1500ec57554Sraf	popl	%ecx
1510ec57554Sraf	testl	%ebp, %ebp	/ negative
1520ec57554Sraf	popl	%esi
1530ec57554Sraf	je	.LL54
1540ec57554Sraf	negl	%eax		/ r
1550ec57554Sraf	adcl	$0, %edx	/, r
1560ec57554Sraf	negl	%edx		/ r
1570ec57554Sraf.LL54:
1580ec57554Sraf	addl	$8, %esp
1590ec57554Sraf	popl	%esi
1600ec57554Sraf	popl	%edi
1610ec57554Sraf	popl	%ebp
1620ec57554Sraf	ret
1630ec57554Sraf	.align	16
1640ec57554Sraf.LL55:
1650ec57554Sraf	negl	%eax		/ x
1660ec57554Sraf	adcl	$0, %edx	/, x
1670ec57554Sraf	negl	%edx		/ x
1680ec57554Sraf	testl	%edi, %edi	/ y
1690ec57554Sraf	movl	%eax, (%esp)	/ x, xt
1700ec57554Sraf	movl	%edx, 4(%esp)	/ x, xt
1710ec57554Sraf	movl	$1, %ebp	/, negative
1720ec57554Sraf	movl	%esi, %eax	/ y, yt
1730ec57554Sraf	movl	%edi, %edx	/ y, yt
1740ec57554Sraf	jns	.LL53
1750ec57554Sraf	.align	16
1760ec57554Sraf.LL56:
1770ec57554Sraf	negl	%eax		/ yt
1780ec57554Sraf	adcl	$0, %edx	/, yt
1790ec57554Sraf	negl	%edx		/ yt
1800ec57554Sraf	xorl	$1, %ebp	/, negative
1810ec57554Sraf	jmp	.LL53
1820ec57554Sraf	SET_SIZE(__divdi3)
1830ec57554Sraf
1840ec57554Sraf/*
1850ec57554Sraf * __moddi3
1860ec57554Sraf *
1870ec57554Sraf * Perform division of two signed 64-bit quantities, returning the
1880ec57554Sraf * quotient in %edx:%eax.
1890ec57554Sraf */
1900ec57554Sraf/ int64_t
1910ec57554Sraf/ __moddi3(int64_t x, int64_t y)
1920ec57554Sraf/ {
1930ec57554Sraf/ 	uint64_t	xt, yt, rem;
1940ec57554Sraf/
1950ec57554Sraf/ 	if (x < 0) {
1960ec57554Sraf/ 		xt = -(uint64_t) x;
1970ec57554Sraf/ 	} else {
1980ec57554Sraf/ 		xt = x;
1990ec57554Sraf/ 	}
2000ec57554Sraf/ 	if (y < 0) {
2010ec57554Sraf/ 		yt = -(uint64_t) y;
2020ec57554Sraf/ 	} else {
2030ec57554Sraf/ 		yt = y;
2040ec57554Sraf/ 	}
2050ec57554Sraf/ 	(void) UDivRem(xt, yt, &rem);
2060ec57554Sraf/ 	return (x < 0 ? (int64_t) - rem : rem);
2070ec57554Sraf/ }
2080ec57554Sraf	ENTRY(__moddi3)
2090ec57554Sraf	pushl	%edi
2100ec57554Sraf	pushl	%esi
2110ec57554Sraf	subl	$20, %esp
2120ec57554Sraf	movl	36(%esp), %ecx	/ x,
2130ec57554Sraf	movl	32(%esp), %esi	/ x,
2140ec57554Sraf	movl	36(%esp), %edi	/ x,
2150ec57554Sraf	testl	%ecx, %ecx
2160ec57554Sraf	movl	40(%esp), %eax	/ y, y
2170ec57554Sraf	movl	44(%esp), %edx	/ y, y
2180ec57554Sraf	movl	%esi, (%esp)	/, xt
2190ec57554Sraf	movl	%edi, 4(%esp)	/, xt
2200ec57554Sraf	js	.LL63
2210ec57554Sraf	testl	%edx, %edx	/ y
2220ec57554Sraf	movl	%eax, %esi	/ y, yt
2230ec57554Sraf	movl	%edx, %edi	/ y, yt
2240ec57554Sraf	js	.LL64
2250ec57554Sraf.LL61:
2260ec57554Sraf	leal	8(%esp), %eax	/, tmp66
2270ec57554Sraf	pushl	%eax		/ tmp66
2280ec57554Sraf	pushl	%edi		/ yt
2290ec57554Sraf	pushl	%esi		/ yt
2300ec57554Sraf	movl	12(%esp), %eax	/ xt, xt
2310ec57554Sraf	movl	16(%esp), %edx	/ xt, xt
2320ec57554Sraf	call	UDivRem
2330ec57554Sraf	addl	$12, %esp
2340ec57554Sraf	movl	36(%esp), %edi	/ x,
2350ec57554Sraf	testl	%edi, %edi
2360ec57554Sraf	movl	8(%esp), %eax	/ rem, rem
2370ec57554Sraf	movl	12(%esp), %edx	/ rem, rem
2380ec57554Sraf	js	.LL65
2390ec57554Sraf	addl	$20, %esp
2400ec57554Sraf	popl	%esi
2410ec57554Sraf	popl	%edi
2420ec57554Sraf	ret
2430ec57554Sraf	.align	16
2440ec57554Sraf.LL63:
2450ec57554Sraf	negl	%esi
2460ec57554Sraf	adcl	$0, %edi
2470ec57554Sraf	negl	%edi
2480ec57554Sraf	testl	%edx, %edx	/ y
2490ec57554Sraf	movl	%esi, (%esp)	/, xt
2500ec57554Sraf	movl	%edi, 4(%esp)	/, xt
2510ec57554Sraf	movl	%eax, %esi	/ y, yt
2520ec57554Sraf	movl	%edx, %edi	/ y, yt
2530ec57554Sraf	jns	.LL61
2540ec57554Sraf	.align	16
2550ec57554Sraf.LL64:
2560ec57554Sraf	negl	%esi		/ yt
2570ec57554Sraf	adcl	$0, %edi	/, yt
2580ec57554Sraf	negl	%edi		/ yt
2590ec57554Sraf	jmp	.LL61
2600ec57554Sraf	.align	16
2610ec57554Sraf.LL65:
2620ec57554Sraf	negl	%eax		/ rem
2630ec57554Sraf	adcl	$0, %edx	/, rem
2640ec57554Sraf	addl	$20, %esp
2650ec57554Sraf	popl	%esi
2660ec57554Sraf	negl	%edx		/ rem
2670ec57554Sraf	popl	%edi
2680ec57554Sraf	ret
2690ec57554Sraf	SET_SIZE(__moddi3)
2700ec57554Sraf
2710ec57554Sraf#endif	/* __lint */
272