xref: /onnv-gate/usr/src/lib/libc/i386/gen/_divdi3.s (revision 7298:b69e27387f74)
11016Sraf/*
21016Sraf * CDDL HEADER START
31016Sraf *
41016Sraf * The contents of this file are subject to the terms of the
5*7298SMark.J.Nelson@Sun.COM * Common Development and Distribution License (the "License").
6*7298SMark.J.Nelson@Sun.COM * You may not use this file except in compliance with the License.
71016Sraf *
81016Sraf * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91016Sraf * or http://www.opensolaris.org/os/licensing.
101016Sraf * See the License for the specific language governing permissions
111016Sraf * and limitations under the License.
121016Sraf *
131016Sraf * When distributing Covered Code, include this CDDL HEADER in each
141016Sraf * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151016Sraf * If applicable, add the following below this CDDL HEADER, with the
161016Sraf * fields enclosed by brackets "[]" replaced with your own identifying
171016Sraf * information: Portions Copyright [yyyy] [name of copyright owner]
181016Sraf *
191016Sraf * CDDL HEADER END
201016Sraf */
211016Sraf
221016Sraf/*
231016Sraf * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
241016Sraf * Use is subject to license terms.
251016Sraf */
261016Sraf
27*7298SMark.J.Nelson@Sun.COM	.file	"_divdi3.s"
281016Sraf
291016Sraf#include <SYS.h>
301016Sraf
311016Sraf/*
321016Sraf * C support for 64-bit modulo and division.
331016Sraf * GNU routines callable from C (though generated by the compiler).
341016Sraf * Hand-customized compiler output - see comments for details.
351016Sraf */
361016Sraf
371016Sraf#if defined(__lint)
381016Sraf
391016Sraf/*ARGSUSED*/
401016Srafuint64_t
411016Sraf__udivdi3(uint64_t a, uint64_t b)
421016Sraf{ return (0); }
431016Sraf
441016Sraf/*ARGSUSED*/
451016Srafuint64_t
461016Sraf__umoddi3(uint64_t a, uint64_t b)
471016Sraf{ return (0); }
481016Sraf
491016Sraf/*ARGSUSED*/
501016Srafint64_t
511016Sraf__divdi3(int64_t a, int64_t b)
521016Sraf{ return (0); }
531016Sraf
541016Sraf/*ARGSUSED*/
551016Srafint64_t
561016Sraf__moddi3(int64_t a, int64_t b)
571016Sraf{ return (0); }
581016Sraf
591016Sraf#else
601016Sraf
611016Sraf/*
621016Sraf * __udivdi3
631016Sraf *
641016Sraf * Perform division of two unsigned 64-bit quantities, returning the
651016Sraf * quotient in %edx:%eax.
661016Sraf */
671016Sraf	ENTRY(__udivdi3)
681016Sraf	movl	4(%esp), %eax	/ x, x
691016Sraf	movl	8(%esp), %edx	/ x, x
701016Sraf	pushl	16(%esp)	/ y
711016Sraf	pushl	16(%esp)
721016Sraf	call	UDiv
731016Sraf	addl	$8, %esp
741016Sraf	ret
751016Sraf	SET_SIZE(__udivdi3)
761016Sraf
771016Sraf/*
781016Sraf * __umoddi3
791016Sraf *
801016Sraf * Perform division of two unsigned 64-bit quantities, returning the
811016Sraf * remainder in %edx:%eax.
821016Sraf */
831016Sraf	ENTRY(__umoddi3)
841016Sraf	subl	$12, %esp
851016Sraf	movl	%esp, %ecx	/, tmp65
861016Sraf	movl	16(%esp), %eax	/ x, x
871016Sraf	movl	20(%esp), %edx	/ x, x
881016Sraf	pushl	%ecx		/ tmp65
891016Sraf	pushl	32(%esp)	/ y
901016Sraf	pushl	32(%esp)
911016Sraf	call	UDivRem
921016Sraf	movl	12(%esp), %eax	/ rem, rem
931016Sraf	movl	16(%esp), %edx	/ rem, rem
941016Sraf	addl	$24, %esp
951016Sraf	ret
961016Sraf	SET_SIZE(__umoddi3)
971016Sraf
981016Sraf/*
991016Sraf * __divdi3
1001016Sraf *
1011016Sraf * Perform division of two signed 64-bit quantities, returning the
1021016Sraf * quotient in %edx:%eax.
1031016Sraf */
1041016Sraf/ int64_t
1051016Sraf/ __divdi3(int64_t x, int64_t y)
1061016Sraf/ {
1071016Sraf/ 	int		negative;
1081016Sraf/ 	uint64_t	xt, yt, r;
1091016Sraf/
1101016Sraf/ 	if (x < 0) {
1111016Sraf/ 		xt = -(uint64_t) x;
1121016Sraf/ 		negative = 1;
1131016Sraf/ 	} else {
1141016Sraf/ 		xt = x;
1151016Sraf/ 		negative = 0;
1161016Sraf/ 	}
1171016Sraf/ 	if (y < 0) {
1181016Sraf/ 		yt = -(uint64_t) y;
1191016Sraf/ 		negative ^= 1;
1201016Sraf/ 	} else {
1211016Sraf/ 		yt = y;
1221016Sraf/ 	}
1231016Sraf/ 	r = UDiv(xt, yt);
1241016Sraf/ 	return (negative ? (int64_t) - r : r);
1251016Sraf/ }
1261016Sraf	ENTRY(__divdi3)
1271016Sraf	pushl	%ebp
1281016Sraf	pushl	%edi
1291016Sraf	pushl	%esi
1301016Sraf	subl	$8, %esp
1311016Sraf	movl	28(%esp), %edx	/ x, x
1321016Sraf	testl	%edx, %edx	/ x
1331016Sraf	movl	24(%esp), %eax	/ x, x
1341016Sraf	movl	32(%esp), %esi	/ y, y
1351016Sraf	movl	36(%esp), %edi	/ y, y
1361016Sraf	js	.LL55
1371016Sraf	xorl	%ebp, %ebp	/ negative
1381016Sraf	testl	%edi, %edi	/ y
1391016Sraf	movl	%eax, (%esp)	/ x, xt
1401016Sraf	movl	%edx, 4(%esp)	/ x, xt
1411016Sraf	movl	%esi, %eax	/ y, yt
1421016Sraf	movl	%edi, %edx	/ y, yt
1431016Sraf	js	.LL56
1441016Sraf.LL53:
1451016Sraf	pushl	%edx		/ yt
1461016Sraf	pushl	%eax		/ yt
1471016Sraf	movl	8(%esp), %eax	/ xt, xt
1481016Sraf	movl	12(%esp), %edx	/ xt, xt
1491016Sraf	call	UDiv
1501016Sraf	popl	%ecx
1511016Sraf	testl	%ebp, %ebp	/ negative
1521016Sraf	popl	%esi
1531016Sraf	je	.LL54
1541016Sraf	negl	%eax		/ r
1551016Sraf	adcl	$0, %edx	/, r
1561016Sraf	negl	%edx		/ r
1571016Sraf.LL54:
1581016Sraf	addl	$8, %esp
1591016Sraf	popl	%esi
1601016Sraf	popl	%edi
1611016Sraf	popl	%ebp
1621016Sraf	ret
1631016Sraf	.align	16
1641016Sraf.LL55:
1651016Sraf	negl	%eax		/ x
1661016Sraf	adcl	$0, %edx	/, x
1671016Sraf	negl	%edx		/ x
1681016Sraf	testl	%edi, %edi	/ y
1691016Sraf	movl	%eax, (%esp)	/ x, xt
1701016Sraf	movl	%edx, 4(%esp)	/ x, xt
1711016Sraf	movl	$1, %ebp	/, negative
1721016Sraf	movl	%esi, %eax	/ y, yt
1731016Sraf	movl	%edi, %edx	/ y, yt
1741016Sraf	jns	.LL53
1751016Sraf	.align	16
1761016Sraf.LL56:
1771016Sraf	negl	%eax		/ yt
1781016Sraf	adcl	$0, %edx	/, yt
1791016Sraf	negl	%edx		/ yt
1801016Sraf	xorl	$1, %ebp	/, negative
1811016Sraf	jmp	.LL53
1821016Sraf	SET_SIZE(__divdi3)
1831016Sraf
1841016Sraf/*
1851016Sraf * __moddi3
1861016Sraf *
1871016Sraf * Perform division of two signed 64-bit quantities, returning the
1881016Sraf * quotient in %edx:%eax.
1891016Sraf */
1901016Sraf/ int64_t
1911016Sraf/ __moddi3(int64_t x, int64_t y)
1921016Sraf/ {
1931016Sraf/ 	uint64_t	xt, yt, rem;
1941016Sraf/
1951016Sraf/ 	if (x < 0) {
1961016Sraf/ 		xt = -(uint64_t) x;
1971016Sraf/ 	} else {
1981016Sraf/ 		xt = x;
1991016Sraf/ 	}
2001016Sraf/ 	if (y < 0) {
2011016Sraf/ 		yt = -(uint64_t) y;
2021016Sraf/ 	} else {
2031016Sraf/ 		yt = y;
2041016Sraf/ 	}
2051016Sraf/ 	(void) UDivRem(xt, yt, &rem);
2061016Sraf/ 	return (x < 0 ? (int64_t) - rem : rem);
2071016Sraf/ }
2081016Sraf	ENTRY(__moddi3)
2091016Sraf	pushl	%edi
2101016Sraf	pushl	%esi
2111016Sraf	subl	$20, %esp
2121016Sraf	movl	36(%esp), %ecx	/ x,
2131016Sraf	movl	32(%esp), %esi	/ x,
2141016Sraf	movl	36(%esp), %edi	/ x,
2151016Sraf	testl	%ecx, %ecx
2161016Sraf	movl	40(%esp), %eax	/ y, y
2171016Sraf	movl	44(%esp), %edx	/ y, y
2181016Sraf	movl	%esi, (%esp)	/, xt
2191016Sraf	movl	%edi, 4(%esp)	/, xt
2201016Sraf	js	.LL63
2211016Sraf	testl	%edx, %edx	/ y
2221016Sraf	movl	%eax, %esi	/ y, yt
2231016Sraf	movl	%edx, %edi	/ y, yt
2241016Sraf	js	.LL64
2251016Sraf.LL61:
2261016Sraf	leal	8(%esp), %eax	/, tmp66
2271016Sraf	pushl	%eax		/ tmp66
2281016Sraf	pushl	%edi		/ yt
2291016Sraf	pushl	%esi		/ yt
2301016Sraf	movl	12(%esp), %eax	/ xt, xt
2311016Sraf	movl	16(%esp), %edx	/ xt, xt
2321016Sraf	call	UDivRem
2331016Sraf	addl	$12, %esp
2341016Sraf	movl	36(%esp), %edi	/ x,
2351016Sraf	testl	%edi, %edi
2361016Sraf	movl	8(%esp), %eax	/ rem, rem
2371016Sraf	movl	12(%esp), %edx	/ rem, rem
2381016Sraf	js	.LL65
2391016Sraf	addl	$20, %esp
2401016Sraf	popl	%esi
2411016Sraf	popl	%edi
2421016Sraf	ret
2431016Sraf	.align	16
2441016Sraf.LL63:
2451016Sraf	negl	%esi
2461016Sraf	adcl	$0, %edi
2471016Sraf	negl	%edi
2481016Sraf	testl	%edx, %edx	/ y
2491016Sraf	movl	%esi, (%esp)	/, xt
2501016Sraf	movl	%edi, 4(%esp)	/, xt
2511016Sraf	movl	%eax, %esi	/ y, yt
2521016Sraf	movl	%edx, %edi	/ y, yt
2531016Sraf	jns	.LL61
2541016Sraf	.align	16
2551016Sraf.LL64:
2561016Sraf	negl	%esi		/ yt
2571016Sraf	adcl	$0, %edi	/, yt
2581016Sraf	negl	%edi		/ yt
2591016Sraf	jmp	.LL61
2601016Sraf	.align	16
2611016Sraf.LL65:
2621016Sraf	negl	%eax		/ rem
2631016Sraf	adcl	$0, %edx	/, rem
2641016Sraf	addl	$20, %esp
2651016Sraf	popl	%esi
2661016Sraf	negl	%edx		/ rem
2671016Sraf	popl	%edi
2681016Sraf	ret
2691016Sraf	SET_SIZE(__moddi3)
2701016Sraf
2711016Sraf#endif	/* __lint */
272