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.
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.
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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 #include "base_conversion.h"
33 __fp_rightshift(unpacked
*pu
, int n
)
35 /* Right shift significand sticky by n bits. */
40 if (n
>= (32 * UNPACKED_SIZE
)) { /* drastic */
41 for (i
= 0; (pu
->significand
[i
] == 0) && (i
< UNPACKED_SIZE
);
43 if (i
>= UNPACKED_SIZE
) {
44 pu
->fpclass
= fp_zero
;
47 for (i
= 0; i
< (UNPACKED_SIZE
- 1); i
++)
48 pu
->significand
[i
] = 0;
49 pu
->significand
[UNPACKED_SIZE
- 1] = 1;
53 while (n
>= 32) { /* big shift */
54 if (pu
->significand
[UNPACKED_SIZE
- 1] != 0)
55 pu
->significand
[UNPACKED_SIZE
- 2] |= 1;
56 for (i
= UNPACKED_SIZE
- 2; i
>= 0; i
--)
57 pu
->significand
[i
+ 1] = pu
->significand
[i
];
58 pu
->significand
[0] = 0;
61 if (n
>= 1) { /* small shift */
62 unsigned int high
, low
, shiftout
= 0;
63 for (i
= 0; i
< UNPACKED_SIZE
; i
++) {
64 high
= pu
->significand
[i
] >> n
;
65 low
= pu
->significand
[i
] << (32 - n
);
66 pu
->significand
[i
] = shiftout
| high
;
70 pu
->significand
[UNPACKED_SIZE
- 1] |= 1;
75 overflow_to_infinity(int sign
, enum fp_direction_type rd
)
77 /* Returns 1 if overflow should go to infinity, 0 if to max finite. */
100 round(unpacked
*pu
, int roundword
, enum fp_direction_type rd
, int *ex
)
102 * Round according to current rounding mode. pu must be shifted to so that
103 * the roundbit is pu->significand[roundword] & 0x80000000
106 int increment
; /* boolean to indicate round up */
108 unsigned msw
; /* msw before increment */
110 for (is
= (roundword
+ 1); is
< UNPACKED_SIZE
; is
++)
111 if (pu
->significand
[is
] != 0) {
112 /* Condense extra bits into sticky bottom of roundword. */
113 pu
->significand
[roundword
] |= 1;
116 if (pu
->significand
[roundword
] == 0)
118 *ex
|= (1 << fp_inexact
);
121 increment
= pu
->significand
[roundword
] >= 0x80000000;
127 increment
= (pu
->sign
== 0) & (pu
->significand
[roundword
] != 0);
130 increment
= (pu
->sign
!= 0) & (pu
->significand
[roundword
] != 0);
134 msw
= pu
->significand
[0]; /* save msw before round */
138 pu
->significand
[is
]++;
140 while ((pu
->significand
[is
] == 0) && (is
> 0));
141 if (pu
->significand
[0] < msw
) { /* rounding carried out */
143 pu
->significand
[0] = 0x80000000;
146 if ((rd
== fp_nearest
) &&
147 (pu
->significand
[roundword
] == 0x80000000)) {
149 pu
->significand
[roundword
- 1] &= ~1; /* force round to even */
154 __pack_single(unpacked
*pu
, single
*px
, enum fp_direction_type rd
,
155 fp_exception_field_type
*ex
)
157 single_equivalence kluge
;
161 kluge
.f
.msw
.sign
= pu
->sign
;
162 switch (pu
->fpclass
) {
164 kluge
.f
.msw
.exponent
= 0;
165 kluge
.f
.msw
.significand
= 0;
169 kluge
.f
.msw
.exponent
= 0xff;
170 kluge
.f
.msw
.significand
= 0;
173 kluge
.f
.msw
.exponent
= 0xff;
174 kluge
.f
.msw
.significand
= 0x400000 |
175 (0x3fffff & (pu
->significand
[0] >> 8));
178 __fp_rightshift(pu
, 8);
179 pu
->exponent
+= SINGLE_BIAS
;
180 if (pu
->exponent
<= 0) {
181 kluge
.f
.msw
.exponent
= 0;
182 __fp_rightshift(pu
, 1 - pu
->exponent
);
183 round(pu
, 1, rd
, &e
);
184 if (pu
->significand
[0] == 0x800000) {
185 /* rounded back up to normal */
186 kluge
.f
.msw
.exponent
= 1;
187 kluge
.f
.msw
.significand
= 0;
188 e
|= (1 << fp_underflow
);
191 if (e
& (1 << fp_inexact
))
192 e
|= (1 << fp_underflow
);
193 kluge
.f
.msw
.significand
= 0x7fffff & pu
->significand
[0];
196 round(pu
, 1, rd
, &e
);
197 if (pu
->significand
[0] == 0x1000000) { /* rounding overflow */
198 pu
->significand
[0] = 0x800000;
201 if (pu
->exponent
>= 0xff) {
202 e
|= (1 << fp_overflow
) | (1 << fp_inexact
);
203 if (overflow_to_infinity(pu
->sign
, rd
))
205 kluge
.f
.msw
.exponent
= 0xfe;
206 kluge
.f
.msw
.significand
= 0x7fffff;
209 kluge
.f
.msw
.exponent
= pu
->exponent
;
210 kluge
.f
.msw
.significand
= 0x7fffff & pu
->significand
[0];
214 *ex
= (fp_exception_field_type
)e
;
218 __pack_double(unpacked
*pu
, double *px
, enum fp_direction_type rd
,
219 fp_exception_field_type
*ex
)
221 double_equivalence kluge
;
225 kluge
.f
.msw
.sign
= pu
->sign
;
226 switch (pu
->fpclass
) {
228 kluge
.f
.msw
.exponent
= 0;
229 kluge
.f
.msw
.significand
= 0;
230 kluge
.f
.significand2
= 0;
234 kluge
.f
.msw
.exponent
= 0x7ff;
235 kluge
.f
.msw
.significand
= 0;
236 kluge
.f
.significand2
= 0;
239 kluge
.f
.msw
.exponent
= 0x7ff;
240 __fp_rightshift(pu
, 11);
241 kluge
.f
.msw
.significand
= 0x80000 |
242 (0x7ffff & pu
->significand
[0]);
243 kluge
.f
.significand2
= pu
->significand
[1];
246 __fp_rightshift(pu
, 11);
247 pu
->exponent
+= DOUBLE_BIAS
;
248 if (pu
->exponent
<= 0) { /* underflow */
249 __fp_rightshift(pu
, 1 - pu
->exponent
);
250 round(pu
, 2, rd
, &e
);
251 if (pu
->significand
[0] == 0x100000) {
252 /* rounded back up to normal */
253 kluge
.f
.msw
.exponent
= 1;
254 kluge
.f
.msw
.significand
= 0;
255 kluge
.f
.significand2
= 0;
256 e
|= (1 << fp_underflow
);
259 if (e
& (1 << fp_inexact
))
260 e
|= (1 << fp_underflow
);
261 kluge
.f
.msw
.exponent
= 0;
262 kluge
.f
.msw
.significand
= 0xfffff & pu
->significand
[0];
263 kluge
.f
.significand2
= pu
->significand
[1];
266 round(pu
, 2, rd
, &e
);
267 if (pu
->significand
[0] == 0x200000) { /* rounding overflow */
268 pu
->significand
[0] = 0x100000;
271 if (pu
->exponent
>= 0x7ff) { /* overflow */
272 e
|= (1 << fp_overflow
) | (1 << fp_inexact
);
273 if (overflow_to_infinity(pu
->sign
, rd
))
275 kluge
.f
.msw
.exponent
= 0x7fe;
276 kluge
.f
.msw
.significand
= 0xfffff;
277 kluge
.f
.significand2
= 0xffffffff;
280 kluge
.f
.msw
.exponent
= pu
->exponent
;
281 kluge
.f
.msw
.significand
= 0xfffff & pu
->significand
[0];
282 kluge
.f
.significand2
= pu
->significand
[1];
287 *ex
= (fp_exception_field_type
)e
;
291 __pack_extended(unpacked
*pu
, extended
*px
, enum fp_direction_type rd
,
292 fp_exception_field_type
*ex
)
294 extended_equivalence kluge
;
298 kluge
.f
.msw
.sign
= pu
->sign
;
299 switch (pu
->fpclass
) {
301 kluge
.f
.msw
.exponent
= 0;
302 kluge
.f
.significand
= 0;
303 kluge
.f
.significand2
= 0;
307 kluge
.f
.msw
.exponent
= 0x7fff;
308 kluge
.f
.significand
= 0x80000000;
309 kluge
.f
.significand2
= 0;
312 kluge
.f
.msw
.exponent
= 0x7fff;
313 kluge
.f
.significand
= 0x40000000 | pu
->significand
[0];
314 kluge
.f
.significand2
= pu
->significand
[1];
317 pu
->exponent
+= EXTENDED_BIAS
;
318 if (pu
->exponent
<= 0) { /* underflow */
319 __fp_rightshift(pu
, 1 - pu
->exponent
);
320 round(pu
, 2, rd
, &e
);
321 if (pu
->significand
[0] == 0x80000000u
) {
322 /* rounded back up to normal */
323 kluge
.f
.msw
.exponent
= 1;
324 kluge
.f
.significand
= 0x80000000u
;
325 kluge
.f
.significand2
= 0;
326 e
|= (1 << fp_underflow
);
329 if (e
& (1 << fp_inexact
))
330 e
|= (1 << fp_underflow
);
331 kluge
.f
.msw
.exponent
= 0;
332 kluge
.f
.significand
= pu
->significand
[0];
333 kluge
.f
.significand2
= pu
->significand
[1];
336 round(pu
, 2, rd
, &e
);
337 if (pu
->exponent
>= 0x7fff) { /* overflow */
338 e
|= (1 << fp_overflow
) | (1 << fp_inexact
);
339 if (overflow_to_infinity(pu
->sign
, rd
))
341 kluge
.f
.msw
.exponent
= 0x7ffe;
342 kluge
.f
.significand
= 0xffffffff;
343 kluge
.f
.significand2
= 0xffffffff;
346 kluge
.f
.msw
.exponent
= pu
->exponent
;
347 kluge
.f
.significand
= pu
->significand
[0];
348 kluge
.f
.significand2
= pu
->significand
[1];
352 (*px
)[0] = kluge
.x
[0];
353 (*px
)[1] = kluge
.x
[1];
354 (*px
)[2] = kluge
.x
[2];
355 *ex
= (fp_exception_field_type
)e
;
359 __pack_quadruple(unpacked
*pu
, quadruple
*px
, enum fp_direction_type rd
,
360 fp_exception_field_type
*ex
)
362 quadruple_equivalence kluge
;
366 kluge
.f
.msw
.sign
= pu
->sign
;
367 switch (pu
->fpclass
) {
369 kluge
.f
.msw
.exponent
= 0;
370 kluge
.f
.msw
.significand
= 0;
371 kluge
.f
.significand2
= 0;
372 kluge
.f
.significand3
= 0;
373 kluge
.f
.significand4
= 0;
377 kluge
.f
.msw
.exponent
= 0x7fff;
378 kluge
.f
.msw
.significand
= 0;
379 kluge
.f
.significand2
= 0;
380 kluge
.f
.significand3
= 0;
381 kluge
.f
.significand4
= 0;
384 kluge
.f
.msw
.exponent
= 0x7fff;
385 __fp_rightshift(pu
, 15);
386 kluge
.f
.msw
.significand
= 0x8000 |
387 (0xffff & pu
->significand
[0]);
388 kluge
.f
.significand2
= pu
->significand
[1];
389 kluge
.f
.significand3
= pu
->significand
[2];
390 kluge
.f
.significand4
= pu
->significand
[3];
393 __fp_rightshift(pu
, 15);
394 pu
->exponent
+= QUAD_BIAS
;
395 if (pu
->exponent
<= 0) { /* underflow */
396 __fp_rightshift(pu
, 1 - pu
->exponent
);
397 round(pu
, 4, rd
, &e
);
398 if (pu
->significand
[0] == 0x10000) {
399 /* rounded back up to normal */
400 kluge
.f
.msw
.exponent
= 1;
401 kluge
.f
.msw
.significand
= 0;
402 kluge
.f
.significand2
= 0;
403 kluge
.f
.significand3
= 0;
404 kluge
.f
.significand4
= 0;
405 e
|= (1 << fp_underflow
);
408 if (e
& (1 << fp_inexact
))
409 e
|= (1 << fp_underflow
);
410 kluge
.f
.msw
.exponent
= 0;
411 kluge
.f
.msw
.significand
= 0xffff & pu
->significand
[0];
412 kluge
.f
.significand2
= pu
->significand
[1];
413 kluge
.f
.significand3
= pu
->significand
[2];
414 kluge
.f
.significand4
= pu
->significand
[3];
417 round(pu
, 4, rd
, &e
);
418 if (pu
->significand
[0] == 0x20000) { /* rounding overflow */
419 pu
->significand
[0] = 0x10000;
422 if (pu
->exponent
>= 0x7fff) { /* overflow */
423 e
|= (1 << fp_overflow
) | (1 << fp_inexact
);
424 if (overflow_to_infinity(pu
->sign
, rd
))
426 kluge
.f
.msw
.exponent
= 0x7ffe;
427 kluge
.f
.msw
.significand
= 0xffff;
428 kluge
.f
.significand2
= 0xffffffff;
429 kluge
.f
.significand3
= 0xffffffff;
430 kluge
.f
.significand4
= 0xffffffff;
433 kluge
.f
.msw
.exponent
= pu
->exponent
;
434 kluge
.f
.msw
.significand
= pu
->significand
[0] & 0xffff;
435 kluge
.f
.significand2
= pu
->significand
[1];
436 kluge
.f
.significand3
= pu
->significand
[2];
437 kluge
.f
.significand4
= pu
->significand
[3];
442 *ex
= (fp_exception_field_type
)e
;