xref: /titanic_51/usr/src/lib/libc/i386/gen/_divdi3.s (revision 6f45ec7b0b964c3be967c4880e8867ac1e7763a5)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License").  You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22
23/*
24 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
25 * Use is subject to license terms.
26 */
27
28#pragma ident	"%Z%%M%	%I%	%E% SMI"
29
30	.file	"%M%"
31
32#include <SYS.h>
33
34/*
35 * C support for 64-bit modulo and division.
36 * GNU routines callable from C (though generated by the compiler).
37 * Hand-customized compiler output - see comments for details.
38 */
39
40#if defined(__lint)
41
42/*ARGSUSED*/
43uint64_t
44__udivdi3(uint64_t a, uint64_t b)
45{ return (0); }
46
47/*ARGSUSED*/
48uint64_t
49__umoddi3(uint64_t a, uint64_t b)
50{ return (0); }
51
52/*ARGSUSED*/
53int64_t
54__divdi3(int64_t a, int64_t b)
55{ return (0); }
56
57/*ARGSUSED*/
58int64_t
59__moddi3(int64_t a, int64_t b)
60{ return (0); }
61
62#else
63
64/*
65 * __udivdi3
66 *
67 * Perform division of two unsigned 64-bit quantities, returning the
68 * quotient in %edx:%eax.
69 */
70	ENTRY(__udivdi3)
71	movl	4(%esp), %eax	/ x, x
72	movl	8(%esp), %edx	/ x, x
73	pushl	16(%esp)	/ y
74	pushl	16(%esp)
75	call	UDiv
76	addl	$8, %esp
77	ret
78	SET_SIZE(__udivdi3)
79
80/*
81 * __umoddi3
82 *
83 * Perform division of two unsigned 64-bit quantities, returning the
84 * remainder in %edx:%eax.
85 */
86	ENTRY(__umoddi3)
87	subl	$12, %esp
88	movl	%esp, %ecx	/, tmp65
89	movl	16(%esp), %eax	/ x, x
90	movl	20(%esp), %edx	/ x, x
91	pushl	%ecx		/ tmp65
92	pushl	32(%esp)	/ y
93	pushl	32(%esp)
94	call	UDivRem
95	movl	12(%esp), %eax	/ rem, rem
96	movl	16(%esp), %edx	/ rem, rem
97	addl	$24, %esp
98	ret
99	SET_SIZE(__umoddi3)
100
101/*
102 * __divdi3
103 *
104 * Perform division of two signed 64-bit quantities, returning the
105 * quotient in %edx:%eax.
106 */
107/ int64_t
108/ __divdi3(int64_t x, int64_t y)
109/ {
110/ 	int		negative;
111/ 	uint64_t	xt, yt, r;
112/
113/ 	if (x < 0) {
114/ 		xt = -(uint64_t) x;
115/ 		negative = 1;
116/ 	} else {
117/ 		xt = x;
118/ 		negative = 0;
119/ 	}
120/ 	if (y < 0) {
121/ 		yt = -(uint64_t) y;
122/ 		negative ^= 1;
123/ 	} else {
124/ 		yt = y;
125/ 	}
126/ 	r = UDiv(xt, yt);
127/ 	return (negative ? (int64_t) - r : r);
128/ }
129	ENTRY(__divdi3)
130	pushl	%ebp
131	pushl	%edi
132	pushl	%esi
133	subl	$8, %esp
134	movl	28(%esp), %edx	/ x, x
135	testl	%edx, %edx	/ x
136	movl	24(%esp), %eax	/ x, x
137	movl	32(%esp), %esi	/ y, y
138	movl	36(%esp), %edi	/ y, y
139	js	.LL55
140	xorl	%ebp, %ebp	/ negative
141	testl	%edi, %edi	/ y
142	movl	%eax, (%esp)	/ x, xt
143	movl	%edx, 4(%esp)	/ x, xt
144	movl	%esi, %eax	/ y, yt
145	movl	%edi, %edx	/ y, yt
146	js	.LL56
147.LL53:
148	pushl	%edx		/ yt
149	pushl	%eax		/ yt
150	movl	8(%esp), %eax	/ xt, xt
151	movl	12(%esp), %edx	/ xt, xt
152	call	UDiv
153	popl	%ecx
154	testl	%ebp, %ebp	/ negative
155	popl	%esi
156	je	.LL54
157	negl	%eax		/ r
158	adcl	$0, %edx	/, r
159	negl	%edx		/ r
160.LL54:
161	addl	$8, %esp
162	popl	%esi
163	popl	%edi
164	popl	%ebp
165	ret
166	.align	16
167.LL55:
168	negl	%eax		/ x
169	adcl	$0, %edx	/, x
170	negl	%edx		/ x
171	testl	%edi, %edi	/ y
172	movl	%eax, (%esp)	/ x, xt
173	movl	%edx, 4(%esp)	/ x, xt
174	movl	$1, %ebp	/, negative
175	movl	%esi, %eax	/ y, yt
176	movl	%edi, %edx	/ y, yt
177	jns	.LL53
178	.align	16
179.LL56:
180	negl	%eax		/ yt
181	adcl	$0, %edx	/, yt
182	negl	%edx		/ yt
183	xorl	$1, %ebp	/, negative
184	jmp	.LL53
185	SET_SIZE(__divdi3)
186
187/*
188 * __moddi3
189 *
190 * Perform division of two signed 64-bit quantities, returning the
191 * quotient in %edx:%eax.
192 */
193/ int64_t
194/ __moddi3(int64_t x, int64_t y)
195/ {
196/ 	uint64_t	xt, yt, rem;
197/
198/ 	if (x < 0) {
199/ 		xt = -(uint64_t) x;
200/ 	} else {
201/ 		xt = x;
202/ 	}
203/ 	if (y < 0) {
204/ 		yt = -(uint64_t) y;
205/ 	} else {
206/ 		yt = y;
207/ 	}
208/ 	(void) UDivRem(xt, yt, &rem);
209/ 	return (x < 0 ? (int64_t) - rem : rem);
210/ }
211	ENTRY(__moddi3)
212	pushl	%edi
213	pushl	%esi
214	subl	$20, %esp
215	movl	36(%esp), %ecx	/ x,
216	movl	32(%esp), %esi	/ x,
217	movl	36(%esp), %edi	/ x,
218	testl	%ecx, %ecx
219	movl	40(%esp), %eax	/ y, y
220	movl	44(%esp), %edx	/ y, y
221	movl	%esi, (%esp)	/, xt
222	movl	%edi, 4(%esp)	/, xt
223	js	.LL63
224	testl	%edx, %edx	/ y
225	movl	%eax, %esi	/ y, yt
226	movl	%edx, %edi	/ y, yt
227	js	.LL64
228.LL61:
229	leal	8(%esp), %eax	/, tmp66
230	pushl	%eax		/ tmp66
231	pushl	%edi		/ yt
232	pushl	%esi		/ yt
233	movl	12(%esp), %eax	/ xt, xt
234	movl	16(%esp), %edx	/ xt, xt
235	call	UDivRem
236	addl	$12, %esp
237	movl	36(%esp), %edi	/ x,
238	testl	%edi, %edi
239	movl	8(%esp), %eax	/ rem, rem
240	movl	12(%esp), %edx	/ rem, rem
241	js	.LL65
242	addl	$20, %esp
243	popl	%esi
244	popl	%edi
245	ret
246	.align	16
247.LL63:
248	negl	%esi
249	adcl	$0, %edi
250	negl	%edi
251	testl	%edx, %edx	/ y
252	movl	%esi, (%esp)	/, xt
253	movl	%edi, 4(%esp)	/, xt
254	movl	%eax, %esi	/ y, yt
255	movl	%edx, %edi	/ y, yt
256	jns	.LL61
257	.align	16
258.LL64:
259	negl	%esi		/ yt
260	adcl	$0, %edi	/, yt
261	negl	%edi		/ yt
262	jmp	.LL61
263	.align	16
264.LL65:
265	negl	%eax		/ rem
266	adcl	$0, %edx	/, rem
267	addl	$20, %esp
268	popl	%esi
269	negl	%edx		/ rem
270	popl	%edi
271	ret
272	SET_SIZE(__moddi3)
273
274#endif	/* __lint */
275