xref: /titanic_51/usr/src/lib/libc/sparc/crt/hwmuldiv.s (revision 613a2f6ba31e891e3d947a356daf5e563d43c1ce)
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 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26	.file	"hwmuldiv.s"
27
28#include <sys/asm_linkage.h>
29
30/*
31 * Versions of .mul .umul .div .udiv .rem .urem written using
32 * appropriate SPARC V8 instructions.
33 */
34
35	ENTRY(.mul)
36	smul	%o0, %o1, %o0
37	rd	%y, %o1
38	sra	%o0, 31, %o2
39	retl
40	cmp	%o1, %o2	! return with Z set if %y == (%o0 >> 31)
41	SET_SIZE(.mul)
42
43	ENTRY(.umul)
44	umul	%o0, %o1, %o0
45	rd	%y, %o1
46	retl
47	tst	%o1		! return with Z set if high order bits are zero
48	SET_SIZE(.umul)
49
50	ENTRY(.div)
51	sra	%o0, 31, %o2
52	wr	%g0, %o2, %y
53	nop
54	nop
55	nop
56	sdivcc	%o0, %o1, %o0
57	bvs,a	1f
58	xnor	%o0, %g0, %o0	! Corbett Correction Factor
591:	retl
60	nop
61	SET_SIZE(.div)
62
63	ENTRY(.udiv)
64	wr	%g0, %g0, %y
65	nop
66	nop
67	retl
68	udiv	%o0, %o1, %o0
69	SET_SIZE(.udiv)
70
71	ENTRY(.rem)
72	sra	%o0, 31, %o4
73	wr	%o4, %g0, %y
74	nop
75	nop
76	nop
77	sdivcc	%o0, %o1, %o2
78	bvs,a	1f
79	xnor	%o2, %g0, %o2	! Corbett Correction Factor
801:	smul	%o2, %o1, %o2
81	retl
82	sub	%o0, %o2, %o0
83	SET_SIZE(.rem)
84
85	ENTRY(.urem)
86	wr	%g0, %g0, %y
87	nop
88	nop
89	nop
90	udiv	%o0, %o1, %o2
91	umul	%o2, %o1, %o2
92	retl
93	sub	%o0, %o2, %o0
94	SET_SIZE(.urem)
95
96/*
97 * v8plus versions of __{u,}{mul,div,rem}64 compiler support routines
98 */
99
100/*
101 * Convert 32-bit arg pairs in %o0:o1 and %o2:%o3 to 64-bit args in %o1 and %o2
102 */
103#define	ARGS_TO_64				\
104	sllx	%o0, 32, %o0;			\
105	srl	%o1, 0, %o1;			\
106	sllx	%o2, 32, %o2;			\
107	srl	%o3, 0, %o3;			\
108	or	%o0, %o1, %o1;			\
109	or	%o2, %o3, %o2
110
111!
112! division, signed
113!
114	ENTRY(__div64)
115	ARGS_TO_64
116	sdivx	%o1, %o2, %o1
117	retl
118	srax	%o1, 32, %o0
119	SET_SIZE(__div64)
120
121!
122! division, unsigned
123!
124	ENTRY(__udiv64)
125	ARGS_TO_64
126	udivx	%o1, %o2, %o1
127	retl
128	srax	%o1, 32, %o0
129	SET_SIZE(__udiv64)
130
131!
132! multiplication, signed and unsigned
133!
134	ENTRY(__mul64)
135	ALTENTRY(__umul64)
136	ARGS_TO_64
137	sub	%o1, %o2, %o0	! %o0 = a - b
138	movrlz	%o0, %g0, %o0	! %o0 = (a < b) ? 0 : a - b
139	sub	%o1, %o0, %o1	! %o1 = (a < b) ? a : b = min(a, b)
140	add	%o2, %o0, %o2	! %o2 = (a < b) ? b : a = max(a, b)
141	mulx	%o1, %o2, %o1	! min(a, b) in "rs1" for early exit
142	retl
143	srax	%o1, 32, %o0
144	SET_SIZE(__mul64)
145	SET_SIZE(__umul64)
146
147!
148! unsigned remainder
149!
150	ENTRY(__urem64)
151	ARGS_TO_64
152	udivx	%o1, %o2, %o3
153	mulx	%o3, %o2, %o3
154	sub	%o1, %o3, %o1
155	retl
156	srax	%o1, 32, %o0
157	SET_SIZE(__urem64)
158
159!
160! signed remainder
161!
162	ENTRY(__rem64)
163	ARGS_TO_64
164	sdivx	%o1, %o2, %o3
165	mulx	%o2, %o3, %o3
166	sub	%o1, %o3, %o1
167	retl
168	srax	%o1, 32, %o0
169	SET_SIZE(__rem64)
170