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 2008 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include "lint.h"
30#include <sys/isa_defs.h>
31#include <floatingpoint.h>
32#include <limits.h>
33#include "libc.h"
34
35/*
36 * Ensure that this "portable" code is only used on big-endian ISAs
37 */
38#if !defined(_BIG_ENDIAN) || defined(_LITTLE_ENDIAN)
39#error	"big-endian only!"
40#endif
41
42/*
43 * Convert a double precision floating point # into a 64-bit unsigned int.
44 *
45 * For compatibility with Sun's other conversion routines, pretend result
46 * is signed if input is negative.
47 */
48unsigned long long
49__dtoull(double dval)
50{
51	int i0;			/* bitslam */
52	unsigned i1;		/* bitslam */
53	int exp;		/* exponent */
54	unsigned int m0;	/* most significant word of mantissa */
55	unsigned int m1;	/* least sig. word of mantissa */
56	unsigned int _fp_current_exceptions = 0;
57	union {
58		int i[2];
59		double d;
60	} u;
61
62	/*
63	 * Extract the exponent and check boundary conditions.
64	 * Notice that the exponent is equal to the bit number where
65	 * we want the most significant bit to live.
66	 */
67	u.d = dval;
68	i0 = u.i[0];
69	i1 = u.i[1];
70
71	exp = ((i0 >> 20) & 0x7ff) - 0x3ff;
72	if (exp < 0) {
73		/* abs(x) < 1.0, so round to 0 */
74		return ((unsigned long long)0);
75	} else if (exp > 63)  {
76		/*
77		 * abs(x) > MAXLLONG; return {MIN,MAX}ULLONG and as
78		 * overflow, Inf, NaN set fp_invalid exception
79		 */
80		_fp_current_exceptions |= (1 << (int)fp_invalid);
81		(void) _Q_set_exception(_fp_current_exceptions);
82		if (i0 < 0)
83			return ((unsigned long long)LLONG_MIN);
84		else
85			return (ULLONG_MAX); /* MAXLONG */
86	}
87
88	/* Extract the mantissa. */
89
90	m0 = 0x80000000 | ((i0 << 11) & 0x7ffff800) | ((i1 >> 21) & 0x7ff);
91	m1 = i1 << 11;
92
93	/*
94	 * The most significant bit of the mantissa is now in bit 63 of m0:m1.
95	 * Shift right by (63 - exp) bits.
96	 */
97	switch (exp) {
98	case 63:
99		break;
100	case 31:
101		m1 = m0;
102		m0 = 0;
103		break;
104	default:
105		if (exp > 31) {
106			m1 = (m0 << (exp - 31)) | (m1 >> (63 - exp));
107			m0 = (m0 >> (63 - exp));
108		} else {
109			m1 = (m0 >> (31 - exp));
110			m0 = 0;
111		}
112		break;
113	}
114
115	if (i0 < 0) {
116		if ((int)m0 < 0) {	/* x < MINLLONG; return MINLLONG */
117			m0 = 0x80000000;
118			m1 = 0;
119		} else {
120			m0 = ~m0;
121			m1 = ~m1;
122			if (++m1 == 0)
123				m0++;
124		}
125	}
126
127	(void) _Q_set_exception(_fp_current_exceptions);
128	return (((unsigned long long)m0 << 32) | m1);
129}
130
131/*
132 * Convert a floating point number into a 64-bit unsigned int.
133 *
134 * For compatibility with Sun's other conversion routines, pretend result
135 * is signed if input is negative.
136 */
137unsigned long long
138__ftoull(float fval)
139{
140	int i0;			/* bitslam */
141	int exp;		/* exponent */
142	unsigned int m0;	/* most significant word of mantissa */
143	unsigned int m1;	/* least sig. word of mantissa */
144	unsigned int _fp_current_exceptions = 0;
145	union {
146		int i;
147		float f;
148	} u;
149
150	/*
151	 * Extract the exponent and check boundary conditions.
152	 * Notice that the exponent is equal to the bit number where
153	 * we want the most significant bit to live.
154	 */
155	u.f = fval;
156	i0 = u.i;
157
158	exp = ((i0 >> 23) & 0xff) - 0x7f;
159	if (exp < 0) {
160		/* abs(x) < 1.0, so round to 0 */
161		return ((unsigned long long)0);
162	} else if (exp > 63)  {
163		/*
164		 * abs(x) > MAXLLONG; return {MIN,MAX}ULLONG and as
165		 * overflow, Inf, NaN set fp_invalid exception
166		 */
167		_fp_current_exceptions |= (1 << (int)fp_invalid);
168		(void) _Q_set_exception(_fp_current_exceptions);
169		if (i0 < 0)
170			return ((unsigned long long)LLONG_MIN);
171		else
172			return (ULLONG_MAX); /* MAXLONG */
173	}
174
175	/* Extract the mantissa. */
176
177	m0 = 0x80000000 | (i0 << 8) & 0x7fffff00;
178	m1 = 0;
179
180	/*
181	 * The most significant bit of the mantissa is now in bit 63 of m0:m1.
182	 * Shift right by (63 - exp) bits.
183	 */
184	switch (exp) {
185	case 63:
186		break;
187	case 31:
188		m1 = m0;
189		m0 = 0;
190		break;
191	default:
192		if (exp > 31) {
193			m1 = m0 << (exp - 31);
194			m0 = (m0 >> (63 - exp));
195		} else {
196			m1 = (m0 >> (31 - exp));
197			m0 = 0;
198		}
199		break;
200	}
201
202	if (i0 < 0) {
203		if ((int)m0 < 0) {	/* x < MINLLONG; return MINLLONG */
204			m0 = 0x80000000;
205			m1 = 0;
206		} else {
207			m0 = ~m0;
208			m1 = ~m1;
209			if (++m1 == 0)
210				m0++;
211		}
212	}
213
214	(void) _Q_set_exception(_fp_current_exceptions);
215	return (((unsigned long long)m0 << 32) | m1);
216}
217
218/*
219 * Convert an extended precision floating point # into a 64-bit unsigned int.
220 *
221 * For compatibility with Sun's other conversion routines, pretend result
222 * is signed if input is negative.
223 */
224unsigned long long
225_Q_qtoull(long double ld)
226{
227	int i0;
228	unsigned int i1, i2;	/* a long double is 128-bit in length */
229	int exp;		/* exponent */
230	unsigned int m0;	/* most significant word of mantissa */
231	unsigned int m1;	/* least sig. word of mantissa */
232	unsigned int _fp_current_exceptions = 0;
233	int	 *plngdbl = (int *)&ld;
234
235	/* Only 96-bits of precision used */
236	i0 = plngdbl[0];
237	i1 = plngdbl[1];
238	i2 = plngdbl[2];
239
240	/*
241	 * Extract the exponent and check boundary conditions.
242	 * Notice that the exponent is equal to the bit number where
243	 * we want the most significant bit to live.
244	 */
245	exp = ((i0 >> 16) & 0x7fff) - 0x3fff;
246	if (exp < 0) {
247		return ((long long)0); /* abs(x) < 1.0, so round to 0 */
248	} else if (exp > 63) {
249		/*
250		 * abs(x) > MAXLLONG; return {MIN,MAX}ULLONG and as
251		 * overflow, Inf, NaN set fp_invalid exception
252		 */
253		_fp_current_exceptions |= (1 << (int)fp_invalid);
254		(void) _Q_set_exception(_fp_current_exceptions);
255		if (i0 < 0)
256			return ((unsigned long long)LLONG_MIN);
257		else
258			return (ULLONG_MAX); /* MAXLONG */
259	}
260
261	/* Extract the mantissa. */
262
263	m0 = 0x80000000 | ((i0<<15) & 0x7fff8000) | ((i1>>17) & 0x7fff);
264	m1 = (i1 << 15) | ((i2 >> 17) & 0x7fff);
265
266	/*
267	 * The most significant bit of the mantissa is now in bit 63 of m0:m1.
268	 * Shift right by (63 - exp) bits.
269	 */
270	switch (exp) {
271	case 63:
272		break;
273	case 31:
274		m1 = m0;
275		m0 = 0;
276		break;
277	default:
278		if (exp > 31) {
279			m1 = (m0 << (exp - 31)) | (m1 >> (63 - exp));
280			m0 = (m0 >> (63 - exp));
281		} else {
282			m1 = (m0 >> (31 - exp));
283			m0 = 0;
284		}
285		break;
286	}
287
288	if (i0 < 0) {
289		if ((int)m0 < 0) {	/* x < MINLLONG; return MINLLONG */
290			m0 = 0x80000000;
291			m1 = 0;
292		} else {
293			m0 = ~m0;
294			m1 = ~m1;
295			if (++m1 == 0)
296				m0++;
297		}
298	}
299
300	(void) _Q_set_exception(_fp_current_exceptions);
301	return (((unsigned long long)m0 << 32) | m1);
302}
303