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
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.
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]
22 #pragma ident "%Z%%M% %I% %E% SMI"
25 * Copyright (c) 1988 by Sun Microsystems, Inc.
28 /* Pack procedures for Sparc FPU simulator. */
31 #include "_Qglobals.h"
34 overflow_to_infinity(sign
)
37 /* Returns 1 if overflow should go to infinity, 0 if to max finite. */
42 switch (fp_direction
) {
63 /* Round according to current rounding mode. */
66 int increment
; /* boolean to indicate round up */
68 sr
= pu
->sticky
|pu
->rounded
;
72 fpu_set_exception(fp_inexact
);
73 switch (fp_direction
) {
75 increment
= pu
->rounded
;
81 increment
= (pu
->sign
== 0) & (sr
!= 0);
84 increment
= (pu
->sign
!= 0) & (sr
!= 0);
89 if (pu
->significand
[3] == 0) {
91 if (pu
->significand
[2] == 0) {
93 if (pu
->significand
[1] == 0) {
94 pu
->significand
[0]++; /* rounding carried out */
95 if( pu
->significand
[0] == 0x20000) {
97 pu
->significand
[0] = 0x10000;
103 if ((fp_direction
== fp_nearest
) &&
104 (pu
->sticky
== 0) && increment
!=0) { /* ambiguous case */
105 pu
->significand
[3] &= 0xfffffffe; /* force round to even */
111 unpacked
*pu
; /* unpacked result */
112 int *px
; /* packed integer */
114 switch (pu
->fpclass
) {
119 if (pu
->exponent
>= 32)
121 fpu_rightshift(pu
, 112 - pu
->exponent
);
123 if (pu
->significand
[3] >= 0x80000000)
124 if ((pu
->sign
== 0)||(pu
->significand
[3] > 0x80000000))
126 *px
= pu
->significand
[3];
138 _fp_current_exceptions
&= ~(1 << (int) fp_inexact
);
139 fpu_set_exception(fp_invalid
);
146 unpacked
*pu
; /* unpacked result */
147 single_type
*px
; /* packed single */
150 switch (pu
->fpclass
) {
162 fpu_rightshift(pu
, 113-24);
164 px
->significand
= 0x400000|(0x3fffff&pu
->significand
[3]);
167 fpu_rightshift(pu
, 113-24);
168 pu
->exponent
+= SINGLE_BIAS
;
169 if (pu
->exponent
<= 0) {
171 fpu_rightshift(pu
, 1 - pu
->exponent
);
173 if (pu
->significand
[3] == 0x800000) { /* rounded
180 if (_fp_current_exceptions
& (1 << fp_inexact
))
181 fpu_set_exception(fp_underflow
);
182 px
->significand
= 0x7fffff & pu
->significand
[3];
186 if (pu
->significand
[3] == 0x1000000) { /* rounding overflow */
187 pu
->significand
[3] = 0x800000;
190 if (pu
->exponent
>= 0xff) {
191 fpu_set_exception(fp_overflow
);
192 fpu_set_exception(fp_inexact
);
193 if (overflow_to_infinity(pu
->sign
))
196 px
->significand
= 0x7fffff;
199 px
->exponent
= pu
->exponent
;
200 px
->significand
= 0x7fffff & pu
->significand
[3];
205 packdouble(pu
, px
, py
)
206 unpacked
*pu
; /* unpacked result */
207 double_type
*px
; /* packed double */
211 switch (pu
->fpclass
) {
219 px
->exponent
= 0x7ff;
225 fpu_rightshift(pu
, 113-53);
226 px
->exponent
= 0x7ff;
227 px
->significand
= 0x80000 | (0x7ffff & pu
->significand
[2]);
228 *py
= pu
->significand
[3];
231 fpu_rightshift(pu
, 113-53);
232 pu
->exponent
+= DOUBLE_BIAS
;
233 if (pu
->exponent
<= 0) { /* underflow */
235 fpu_rightshift(pu
, 1 - pu
->exponent
);
237 if (pu
->significand
[2] == 0x100000) { /* rounded
245 if (_fp_current_exceptions
& (1 << fp_inexact
))
246 fpu_set_exception(fp_underflow
);
248 px
->significand
= 0xfffff & pu
->significand
[2];
249 *py
= pu
->significand
[3];
253 if (pu
->significand
[2] == 0x200000) { /* rounding overflow */
254 pu
->significand
[2] = 0x100000;
257 if (pu
->exponent
>= 0x7ff) { /* overflow */
258 fpu_set_exception(fp_overflow
);
259 fpu_set_exception(fp_inexact
);
260 if (overflow_to_infinity(pu
->sign
))
262 px
->exponent
= 0x7fe;
263 px
->significand
= 0xfffff;
267 px
->exponent
= pu
->exponent
;
268 px
->significand
= 0xfffff & pu
->significand
[2];
269 *py
= pu
->significand
[3];
275 packextended(pu
, px
, py
, pz
, pw
)
276 unpacked
*pu
; /* unpacked result */
277 extended_type
*px
; /* packed extended */
278 unsigned *py
, *pz
, *pw
;
281 switch (pu
->fpclass
) {
291 px
->exponent
= 0x7fff;
299 px
->exponent
= 0x7fff;
300 px
->significand
= 0x8000 | pu
->significand
[0]; /* Insure quiet
302 *py
= pu
->significand
[1];
303 *pz
= pu
->significand
[2];
304 *pw
= pu
->significand
[3];
307 pu
->exponent
+= EXTENDED_BIAS
;
308 if (pu
->exponent
<= 0) { /* underflow */
309 fpu_rightshift(pu
, 1-pu
->exponent
);
311 if (pu
->significand
[0] < 0x00010000) { /* not rounded
314 if (_fp_current_exceptions
& (1 << fp_inexact
))
315 fpu_set_exception(fp_underflow
);
319 px
->significand
= pu
->significand
[0];
320 *py
= pu
->significand
[1];
321 *pz
= pu
->significand
[2];
322 *pw
= pu
->significand
[3];
325 round(pu
); /* rounding overflow handled in round() */
326 if (pu
->exponent
>= 0x7fff) { /* overflow */
327 fpu_set_exception(fp_overflow
);
328 fpu_set_exception(fp_inexact
);
329 if (overflow_to_infinity(pu
->sign
))
331 px
->exponent
= 0x7ffe; /* overflow to max norm */
332 px
->significand
= 0xffff;
338 px
->exponent
= pu
->exponent
;
339 px
->significand
= pu
->significand
[0];
340 *py
= pu
->significand
[1];
341 *pz
= pu
->significand
[2];
342 *pw
= pu
->significand
[3];
348 _fp_pack(pu
, n
, type
)
349 unpacked
*pu
; /* unpacked operand */
350 int *n
; /* output result's address */
351 enum fp_op_type type
; /* type of datum */
372 if((*(int*)&t
)!=0) {i0
=0;i1
=1;} else {i0
=1;i1
=0;}
373 packdouble(pu
, &x
,&n
[i1
]);
383 switch (fp_precision
) { /* Implement extended
384 * rounding precision mode. */
390 unpacksingle(pu
, tx
);
397 packdouble(pu
, &tx
, &ty
);
399 unpackdouble(pu
, tx
, ty
);
402 case fp_precision_3
: /* rounded to 64 bits */
404 k
= pu
->exponent
+ EXTENDED_BIAS
;
407 fpu_rightshift(pu
,113-64);
409 pu
->sticky
=pu
->rounded
=0;
418 if((*(int*)&t
)!=0) {i0
=0;i1
=1;i2
=2;i3
=3;}
419 else {i0
=3;i1
=2;i2
=1;i3
=0;}
420 packextended(pu
, &x
, &n
[i1
], &n
[i2
], &n
[i3
]);