xref: /illumos-gate/usr/src/lib/libc/i386/gen/_divdi3.s (revision 9a70fc3b)
17c478bd9Sstevel@tonic-gate/*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * 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.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
210ec57554Sraf
227c478bd9Sstevel@tonic-gate/*
237c478bd9Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
27*9a70fc3bSMark J. Nelson	.file	"_divdi3.s"
287c478bd9Sstevel@tonic-gate
297c478bd9Sstevel@tonic-gate#include <SYS.h>
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate/*
327c478bd9Sstevel@tonic-gate * C support for 64-bit modulo and division.
337c478bd9Sstevel@tonic-gate * GNU routines callable from C (though generated by the compiler).
347c478bd9Sstevel@tonic-gate * Hand-customized compiler output - see comments for details.
357c478bd9Sstevel@tonic-gate */
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate#if defined(__lint)
387c478bd9Sstevel@tonic-gate
397c478bd9Sstevel@tonic-gate/*ARGSUSED*/
407c478bd9Sstevel@tonic-gateuint64_t
417c478bd9Sstevel@tonic-gate__udivdi3(uint64_t a, uint64_t b)
427c478bd9Sstevel@tonic-gate{ return (0); }
437c478bd9Sstevel@tonic-gate
447c478bd9Sstevel@tonic-gate/*ARGSUSED*/
457c478bd9Sstevel@tonic-gateuint64_t
467c478bd9Sstevel@tonic-gate__umoddi3(uint64_t a, uint64_t b)
477c478bd9Sstevel@tonic-gate{ return (0); }
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate/*ARGSUSED*/
507c478bd9Sstevel@tonic-gateint64_t
517c478bd9Sstevel@tonic-gate__divdi3(int64_t a, int64_t b)
527c478bd9Sstevel@tonic-gate{ return (0); }
537c478bd9Sstevel@tonic-gate
547c478bd9Sstevel@tonic-gate/*ARGSUSED*/
557c478bd9Sstevel@tonic-gateint64_t
567c478bd9Sstevel@tonic-gate__moddi3(int64_t a, int64_t b)
577c478bd9Sstevel@tonic-gate{ return (0); }
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate#else
607c478bd9Sstevel@tonic-gate
617c478bd9Sstevel@tonic-gate/*
627c478bd9Sstevel@tonic-gate * __udivdi3
637c478bd9Sstevel@tonic-gate *
647c478bd9Sstevel@tonic-gate * Perform division of two unsigned 64-bit quantities, returning the
657c478bd9Sstevel@tonic-gate * quotient in %edx:%eax.
667c478bd9Sstevel@tonic-gate */
677c478bd9Sstevel@tonic-gate	ENTRY(__udivdi3)
687c478bd9Sstevel@tonic-gate	movl	4(%esp), %eax	/ x, x
697c478bd9Sstevel@tonic-gate	movl	8(%esp), %edx	/ x, x
707c478bd9Sstevel@tonic-gate	pushl	16(%esp)	/ y
717c478bd9Sstevel@tonic-gate	pushl	16(%esp)
727c478bd9Sstevel@tonic-gate	call	UDiv
737c478bd9Sstevel@tonic-gate	addl	$8, %esp
747c478bd9Sstevel@tonic-gate	ret
757c478bd9Sstevel@tonic-gate	SET_SIZE(__udivdi3)
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate/*
787c478bd9Sstevel@tonic-gate * __umoddi3
797c478bd9Sstevel@tonic-gate *
807c478bd9Sstevel@tonic-gate * Perform division of two unsigned 64-bit quantities, returning the
817c478bd9Sstevel@tonic-gate * remainder in %edx:%eax.
827c478bd9Sstevel@tonic-gate */
837c478bd9Sstevel@tonic-gate	ENTRY(__umoddi3)
847c478bd9Sstevel@tonic-gate	subl	$12, %esp
857c478bd9Sstevel@tonic-gate	movl	%esp, %ecx	/, tmp65
867c478bd9Sstevel@tonic-gate	movl	16(%esp), %eax	/ x, x
877c478bd9Sstevel@tonic-gate	movl	20(%esp), %edx	/ x, x
887c478bd9Sstevel@tonic-gate	pushl	%ecx		/ tmp65
897c478bd9Sstevel@tonic-gate	pushl	32(%esp)	/ y
907c478bd9Sstevel@tonic-gate	pushl	32(%esp)
917c478bd9Sstevel@tonic-gate	call	UDivRem
927c478bd9Sstevel@tonic-gate	movl	12(%esp), %eax	/ rem, rem
937c478bd9Sstevel@tonic-gate	movl	16(%esp), %edx	/ rem, rem
947c478bd9Sstevel@tonic-gate	addl	$24, %esp
957c478bd9Sstevel@tonic-gate	ret
967c478bd9Sstevel@tonic-gate	SET_SIZE(__umoddi3)
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate/*
997c478bd9Sstevel@tonic-gate * __divdi3
1007c478bd9Sstevel@tonic-gate *
1017c478bd9Sstevel@tonic-gate * Perform division of two signed 64-bit quantities, returning the
1027c478bd9Sstevel@tonic-gate * quotient in %edx:%eax.
1037c478bd9Sstevel@tonic-gate */
1047c478bd9Sstevel@tonic-gate/ int64_t
1057c478bd9Sstevel@tonic-gate/ __divdi3(int64_t x, int64_t y)
1067c478bd9Sstevel@tonic-gate/ {
1077c478bd9Sstevel@tonic-gate/ 	int		negative;
1087c478bd9Sstevel@tonic-gate/ 	uint64_t	xt, yt, r;
1097c478bd9Sstevel@tonic-gate/
1107c478bd9Sstevel@tonic-gate/ 	if (x < 0) {
1117c478bd9Sstevel@tonic-gate/ 		xt = -(uint64_t) x;
1127c478bd9Sstevel@tonic-gate/ 		negative = 1;
1137c478bd9Sstevel@tonic-gate/ 	} else {
1147c478bd9Sstevel@tonic-gate/ 		xt = x;
1157c478bd9Sstevel@tonic-gate/ 		negative = 0;
1167c478bd9Sstevel@tonic-gate/ 	}
1177c478bd9Sstevel@tonic-gate/ 	if (y < 0) {
1187c478bd9Sstevel@tonic-gate/ 		yt = -(uint64_t) y;
1197c478bd9Sstevel@tonic-gate/ 		negative ^= 1;
1207c478bd9Sstevel@tonic-gate/ 	} else {
1217c478bd9Sstevel@tonic-gate/ 		yt = y;
1227c478bd9Sstevel@tonic-gate/ 	}
1237c478bd9Sstevel@tonic-gate/ 	r = UDiv(xt, yt);
1247c478bd9Sstevel@tonic-gate/ 	return (negative ? (int64_t) - r : r);
1257c478bd9Sstevel@tonic-gate/ }
1267c478bd9Sstevel@tonic-gate	ENTRY(__divdi3)
1277c478bd9Sstevel@tonic-gate	pushl	%ebp
1287c478bd9Sstevel@tonic-gate	pushl	%edi
1297c478bd9Sstevel@tonic-gate	pushl	%esi
1307c478bd9Sstevel@tonic-gate	subl	$8, %esp
1317c478bd9Sstevel@tonic-gate	movl	28(%esp), %edx	/ x, x
1327c478bd9Sstevel@tonic-gate	testl	%edx, %edx	/ x
1337c478bd9Sstevel@tonic-gate	movl	24(%esp), %eax	/ x, x
1347c478bd9Sstevel@tonic-gate	movl	32(%esp), %esi	/ y, y
1357c478bd9Sstevel@tonic-gate	movl	36(%esp), %edi	/ y, y
1367c478bd9Sstevel@tonic-gate	js	.LL55
1377c478bd9Sstevel@tonic-gate	xorl	%ebp, %ebp	/ negative
1387c478bd9Sstevel@tonic-gate	testl	%edi, %edi	/ y
1397c478bd9Sstevel@tonic-gate	movl	%eax, (%esp)	/ x, xt
1407c478bd9Sstevel@tonic-gate	movl	%edx, 4(%esp)	/ x, xt
1417c478bd9Sstevel@tonic-gate	movl	%esi, %eax	/ y, yt
1427c478bd9Sstevel@tonic-gate	movl	%edi, %edx	/ y, yt
1437c478bd9Sstevel@tonic-gate	js	.LL56
1447c478bd9Sstevel@tonic-gate.LL53:
1457c478bd9Sstevel@tonic-gate	pushl	%edx		/ yt
1467c478bd9Sstevel@tonic-gate	pushl	%eax		/ yt
1477c478bd9Sstevel@tonic-gate	movl	8(%esp), %eax	/ xt, xt
1487c478bd9Sstevel@tonic-gate	movl	12(%esp), %edx	/ xt, xt
1497c478bd9Sstevel@tonic-gate	call	UDiv
1507c478bd9Sstevel@tonic-gate	popl	%ecx
1517c478bd9Sstevel@tonic-gate	testl	%ebp, %ebp	/ negative
1527c478bd9Sstevel@tonic-gate	popl	%esi
1537c478bd9Sstevel@tonic-gate	je	.LL54
1547c478bd9Sstevel@tonic-gate	negl	%eax		/ r
1557c478bd9Sstevel@tonic-gate	adcl	$0, %edx	/, r
1567c478bd9Sstevel@tonic-gate	negl	%edx		/ r
1577c478bd9Sstevel@tonic-gate.LL54:
1587c478bd9Sstevel@tonic-gate	addl	$8, %esp
1597c478bd9Sstevel@tonic-gate	popl	%esi
1607c478bd9Sstevel@tonic-gate	popl	%edi
1617c478bd9Sstevel@tonic-gate	popl	%ebp
1627c478bd9Sstevel@tonic-gate	ret
1637c478bd9Sstevel@tonic-gate	.align	16
1647c478bd9Sstevel@tonic-gate.LL55:
1657c478bd9Sstevel@tonic-gate	negl	%eax		/ x
1667c478bd9Sstevel@tonic-gate	adcl	$0, %edx	/, x
1677c478bd9Sstevel@tonic-gate	negl	%edx		/ x
1687c478bd9Sstevel@tonic-gate	testl	%edi, %edi	/ y
1697c478bd9Sstevel@tonic-gate	movl	%eax, (%esp)	/ x, xt
1707c478bd9Sstevel@tonic-gate	movl	%edx, 4(%esp)	/ x, xt
1717c478bd9Sstevel@tonic-gate	movl	$1, %ebp	/, negative
1727c478bd9Sstevel@tonic-gate	movl	%esi, %eax	/ y, yt
1737c478bd9Sstevel@tonic-gate	movl	%edi, %edx	/ y, yt
1747c478bd9Sstevel@tonic-gate	jns	.LL53
1757c478bd9Sstevel@tonic-gate	.align	16
1767c478bd9Sstevel@tonic-gate.LL56:
1777c478bd9Sstevel@tonic-gate	negl	%eax		/ yt
1787c478bd9Sstevel@tonic-gate	adcl	$0, %edx	/, yt
1797c478bd9Sstevel@tonic-gate	negl	%edx		/ yt
1807c478bd9Sstevel@tonic-gate	xorl	$1, %ebp	/, negative
1817c478bd9Sstevel@tonic-gate	jmp	.LL53
1827c478bd9Sstevel@tonic-gate	SET_SIZE(__divdi3)
1837c478bd9Sstevel@tonic-gate
1847c478bd9Sstevel@tonic-gate/*
1857c478bd9Sstevel@tonic-gate * __moddi3
1867c478bd9Sstevel@tonic-gate *
1877c478bd9Sstevel@tonic-gate * Perform division of two signed 64-bit quantities, returning the
1887c478bd9Sstevel@tonic-gate * quotient in %edx:%eax.
1897c478bd9Sstevel@tonic-gate */
1907c478bd9Sstevel@tonic-gate/ int64_t
1917c478bd9Sstevel@tonic-gate/ __moddi3(int64_t x, int64_t y)
1927c478bd9Sstevel@tonic-gate/ {
1937c478bd9Sstevel@tonic-gate/ 	uint64_t	xt, yt, rem;
1947c478bd9Sstevel@tonic-gate/
1957c478bd9Sstevel@tonic-gate/ 	if (x < 0) {
1967c478bd9Sstevel@tonic-gate/ 		xt = -(uint64_t) x;
1977c478bd9Sstevel@tonic-gate/ 	} else {
1987c478bd9Sstevel@tonic-gate/ 		xt = x;
1997c478bd9Sstevel@tonic-gate/ 	}
2007c478bd9Sstevel@tonic-gate/ 	if (y < 0) {
2017c478bd9Sstevel@tonic-gate/ 		yt = -(uint64_t) y;
2027c478bd9Sstevel@tonic-gate/ 	} else {
2037c478bd9Sstevel@tonic-gate/ 		yt = y;
2047c478bd9Sstevel@tonic-gate/ 	}
2057c478bd9Sstevel@tonic-gate/ 	(void) UDivRem(xt, yt, &rem);
2067c478bd9Sstevel@tonic-gate/ 	return (x < 0 ? (int64_t) - rem : rem);
2077c478bd9Sstevel@tonic-gate/ }
2087c478bd9Sstevel@tonic-gate	ENTRY(__moddi3)
2097c478bd9Sstevel@tonic-gate	pushl	%edi
2107c478bd9Sstevel@tonic-gate	pushl	%esi
2117c478bd9Sstevel@tonic-gate	subl	$20, %esp
2127c478bd9Sstevel@tonic-gate	movl	36(%esp), %ecx	/ x,
2137c478bd9Sstevel@tonic-gate	movl	32(%esp), %esi	/ x,
2147c478bd9Sstevel@tonic-gate	movl	36(%esp), %edi	/ x,
2157c478bd9Sstevel@tonic-gate	testl	%ecx, %ecx
2167c478bd9Sstevel@tonic-gate	movl	40(%esp), %eax	/ y, y
2177c478bd9Sstevel@tonic-gate	movl	44(%esp), %edx	/ y, y
2187c478bd9Sstevel@tonic-gate	movl	%esi, (%esp)	/, xt
2197c478bd9Sstevel@tonic-gate	movl	%edi, 4(%esp)	/, xt
2207c478bd9Sstevel@tonic-gate	js	.LL63
2217c478bd9Sstevel@tonic-gate	testl	%edx, %edx	/ y
2227c478bd9Sstevel@tonic-gate	movl	%eax, %esi	/ y, yt
2237c478bd9Sstevel@tonic-gate	movl	%edx, %edi	/ y, yt
2247c478bd9Sstevel@tonic-gate	js	.LL64
2257c478bd9Sstevel@tonic-gate.LL61:
2267c478bd9Sstevel@tonic-gate	leal	8(%esp), %eax	/, tmp66
2277c478bd9Sstevel@tonic-gate	pushl	%eax		/ tmp66
2287c478bd9Sstevel@tonic-gate	pushl	%edi		/ yt
2297c478bd9Sstevel@tonic-gate	pushl	%esi		/ yt
2307c478bd9Sstevel@tonic-gate	movl	12(%esp), %eax	/ xt, xt
2317c478bd9Sstevel@tonic-gate	movl	16(%esp), %edx	/ xt, xt
2327c478bd9Sstevel@tonic-gate	call	UDivRem
2337c478bd9Sstevel@tonic-gate	addl	$12, %esp
2347c478bd9Sstevel@tonic-gate	movl	36(%esp), %edi	/ x,
2357c478bd9Sstevel@tonic-gate	testl	%edi, %edi
2367c478bd9Sstevel@tonic-gate	movl	8(%esp), %eax	/ rem, rem
2377c478bd9Sstevel@tonic-gate	movl	12(%esp), %edx	/ rem, rem
2387c478bd9Sstevel@tonic-gate	js	.LL65
2397c478bd9Sstevel@tonic-gate	addl	$20, %esp
2407c478bd9Sstevel@tonic-gate	popl	%esi
2417c478bd9Sstevel@tonic-gate	popl	%edi
2427c478bd9Sstevel@tonic-gate	ret
2437c478bd9Sstevel@tonic-gate	.align	16
2447c478bd9Sstevel@tonic-gate.LL63:
2457c478bd9Sstevel@tonic-gate	negl	%esi
2467c478bd9Sstevel@tonic-gate	adcl	$0, %edi
2477c478bd9Sstevel@tonic-gate	negl	%edi
2487c478bd9Sstevel@tonic-gate	testl	%edx, %edx	/ y
2497c478bd9Sstevel@tonic-gate	movl	%esi, (%esp)	/, xt
2507c478bd9Sstevel@tonic-gate	movl	%edi, 4(%esp)	/, xt
2517c478bd9Sstevel@tonic-gate	movl	%eax, %esi	/ y, yt
2527c478bd9Sstevel@tonic-gate	movl	%edx, %edi	/ y, yt
2537c478bd9Sstevel@tonic-gate	jns	.LL61
2547c478bd9Sstevel@tonic-gate	.align	16
2557c478bd9Sstevel@tonic-gate.LL64:
2567c478bd9Sstevel@tonic-gate	negl	%esi		/ yt
2577c478bd9Sstevel@tonic-gate	adcl	$0, %edi	/, yt
2587c478bd9Sstevel@tonic-gate	negl	%edi		/ yt
2597c478bd9Sstevel@tonic-gate	jmp	.LL61
2607c478bd9Sstevel@tonic-gate	.align	16
2617c478bd9Sstevel@tonic-gate.LL65:
2627c478bd9Sstevel@tonic-gate	negl	%eax		/ rem
2637c478bd9Sstevel@tonic-gate	adcl	$0, %edx	/, rem
2647c478bd9Sstevel@tonic-gate	addl	$20, %esp
2657c478bd9Sstevel@tonic-gate	popl	%esi
2667c478bd9Sstevel@tonic-gate	negl	%edx		/ rem
2677c478bd9Sstevel@tonic-gate	popl	%edi
2687c478bd9Sstevel@tonic-gate	ret
2697c478bd9Sstevel@tonic-gate	SET_SIZE(__moddi3)
2707c478bd9Sstevel@tonic-gate
2717c478bd9Sstevel@tonic-gate#endif	/* __lint */
272