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