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]
23 * Copyright 1988,1995-1996,2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 /* Pack procedures for Sparc FPU simulator. */
31 #include <sys/fpu/fpu_simulator.h>
32 #include <sys/fpu/globals.h>
35 * Returns 1 if overflow should go to infinity, 0 if to max finite.
39 fp_simd_type
*pfpsd
, /* Pointer to simulator data */
40 int sign
) /* negative or positive */
44 switch (pfpsd
->fp_direction
) {
62 * Round according to current rounding mode.
66 fp_simd_type
*pfpsd
, /* Pointer to simulator data */
67 unpacked
*pu
) /* unpacked result */
69 int increment
; /* boolean to indicate round up */
72 sr
= pu
->sticky
|pu
->rounded
;
76 fpu_set_exception(pfpsd
, fp_inexact
);
77 switch (pfpsd
->fp_direction
) {
79 increment
= pu
->rounded
;
85 increment
= (pu
->sign
== 0) & (sr
!= 0);
88 increment
= (pu
->sign
!= 0) & (sr
!= 0);
93 if (pu
->significand
[3] == 0) {
95 if (pu
->significand
[2] == 0) {
97 if (pu
->significand
[1] == 0) {
98 pu
->significand
[0]++; /* rounding carried out */
99 if (pu
->significand
[0] == 0x20000) {
101 pu
->significand
[0] = 0x10000;
107 if ((pfpsd
->fp_direction
== fp_nearest
) &&
108 (pu
->sticky
== 0) && increment
!= 0) { /* ambiguous case */
109 pu
->significand
[3] &= 0xfffffffe; /* force round to even */
115 fp_simd_type
*pfpsd
, /* Pointer to simulator data */
116 unpacked
*pu
, /* unpacked result */
117 int32_t *px
) /* packed int32_t */
119 switch (pu
->fpclass
) {
124 if (pu
->exponent
>= 32)
126 fpu_rightshift(pu
, 112 - pu
->exponent
);
128 if (pu
->significand
[3] >= 0x80000000)
129 if ((pu
->sign
== 0)||(pu
->significand
[3] > 0x80000000))
131 *px
= pu
->significand
[3];
143 pfpsd
->fp_current_exceptions
&= ~(1 << (int)fp_inexact
);
144 fpu_set_exception(pfpsd
, fp_invalid
);
151 fp_simd_type
*pfpsd
, /* Pointer to simulator data */
152 unpacked
*pu
, /* unpacked result */
153 int64_t *px
) /* packed int64_t */
160 switch (pu
->fpclass
) {
165 if (pu
->exponent
>= 64)
167 fpu_rightshift(pu
, 112 - pu
->exponent
);
169 if (pu
->significand
[2] >= 0x80000000)
170 if ((pu
->sign
== 0) ||
171 (pu
->significand
[2] > 0x80000000) ||
172 (((pu
->significand
[2] == 0x80000000) &&
173 (pu
->significand
[3] > 0))))
175 x
.i
[0] = pu
->significand
[2];
176 x
.i
[1] = pu
->significand
[3];
186 *px
= (int64_t)0x8000000000000000;
188 *px
= (int64_t)0x7fffffffffffffff;
189 pfpsd
->fp_current_exceptions
&= ~(1 << (int)fp_inexact
);
190 fpu_set_exception(pfpsd
, fp_invalid
);
197 fp_simd_type
*pfpsd
, /* Pointer to simulator data */
198 unpacked
*pu
, /* unpacked result */
199 single_type
*px
) /* packed single */
202 switch (pu
->fpclass
) {
214 fpu_rightshift(pu
, 113-24);
216 px
->significand
= 0x400000|(0x3fffff&pu
->significand
[3]);
219 fpu_rightshift(pu
, 113-24);
220 pu
->exponent
+= SINGLE_BIAS
;
221 if (pu
->exponent
<= 0) {
223 fpu_rightshift(pu
, 1 - pu
->exponent
);
225 if (pu
->significand
[3] == 0x800000) {
233 fpu_set_exception(pfpsd
, fp_inexact
);
235 px
->significand
= 0x7fffff & pu
->significand
[3];
237 if (pfpsd
->fp_current_exceptions
& (1 << fp_inexact
))
238 fpu_set_exception(pfpsd
, fp_underflow
);
239 if (pfpsd
->fp_fsrtem
& (1<<fp_underflow
)) {
240 fpu_set_exception(pfpsd
, fp_underflow
);
241 pfpsd
->fp_current_exceptions
&=
242 ~(1 << (int)fp_inexact
);
247 if (pu
->significand
[3] == 0x1000000) { /* rounding overflow */
248 pu
->significand
[3] = 0x800000;
251 if (pu
->exponent
>= 0xff) {
252 fpu_set_exception(pfpsd
, fp_overflow
);
253 fpu_set_exception(pfpsd
, fp_inexact
);
254 if (pfpsd
->fp_fsrtem
& (1<<fp_overflow
)) {
255 pfpsd
->fp_current_exceptions
&=
256 ~(1 << (int)fp_inexact
);
258 if (overflow_to_infinity(pfpsd
, pu
->sign
))
261 px
->significand
= 0x7fffff;
264 px
->exponent
= pu
->exponent
;
265 px
->significand
= 0x7fffff & pu
->significand
[3];
271 fp_simd_type
*pfpsd
, /* Pointer to simulator data */
272 unpacked
*pu
, /* unpacked result */
273 double_type
*px
, /* packed double, sign/exponent/upper 20 bits */
274 uint_t
*py
) /* and the lower 32 bits of the significand */
277 switch (pu
->fpclass
) {
285 px
->exponent
= 0x7ff;
291 fpu_rightshift(pu
, 113-53);
292 px
->exponent
= 0x7ff;
293 px
->significand
= 0x80000 | (0x7ffff & pu
->significand
[2]);
294 *py
= pu
->significand
[3];
297 fpu_rightshift(pu
, 113-53);
298 pu
->exponent
+= DOUBLE_BIAS
;
299 if (pu
->exponent
<= 0) { /* underflow */
301 fpu_rightshift(pu
, 1 - pu
->exponent
);
303 if (pu
->significand
[2] == 0x100000) {
312 fpu_set_exception(pfpsd
, fp_inexact
);
315 px
->significand
= 0xfffff & pu
->significand
[2];
316 *py
= pu
->significand
[3];
318 if (pfpsd
->fp_current_exceptions
& (1 << fp_inexact
))
319 fpu_set_exception(pfpsd
, fp_underflow
);
320 if (pfpsd
->fp_fsrtem
& (1<<fp_underflow
)) {
321 fpu_set_exception(pfpsd
, fp_underflow
);
322 pfpsd
->fp_current_exceptions
&=
323 ~(1 << (int)fp_inexact
);
328 if (pu
->significand
[2] == 0x200000) { /* rounding overflow */
329 pu
->significand
[2] = 0x100000;
332 if (pu
->exponent
>= 0x7ff) { /* overflow */
333 fpu_set_exception(pfpsd
, fp_overflow
);
334 fpu_set_exception(pfpsd
, fp_inexact
);
335 if (pfpsd
->fp_fsrtem
& (1<<fp_overflow
)) {
336 pfpsd
->fp_current_exceptions
&=
337 ~(1 << (int)fp_inexact
);
339 if (overflow_to_infinity(pfpsd
, pu
->sign
))
341 px
->exponent
= 0x7fe;
342 px
->significand
= 0xfffff;
346 px
->exponent
= pu
->exponent
;
347 px
->significand
= 0xfffff & pu
->significand
[2];
348 *py
= pu
->significand
[3];
355 fp_simd_type
*pfpsd
, /* Pointer to simulator data */
356 unpacked
*pu
, /* unpacked result */
357 extended_type
*px
, /* packed extended, sign/exponent/16 bits */
358 uint_t
*py
, /* 2nd word of extended significand */
359 uint_t
*pz
, /* 3rd word of extended significand */
360 uint_t
*pw
) /* 4th word of extended significand */
363 switch (pu
->fpclass
) {
373 px
->exponent
= 0x7fff;
381 px
->exponent
= 0x7fff;
382 px
->significand
= 0x8000 | pu
->significand
[0];
387 *py
= pu
->significand
[1];
388 *pz
= pu
->significand
[2];
389 *pw
= pu
->significand
[3];
392 pu
->exponent
+= EXTENDED_BIAS
;
393 if (pu
->exponent
<= 0) { /* underflow */
394 fpu_rightshift(pu
, 1-pu
->exponent
);
396 if (pu
->significand
[0] < 0x00010000) {
405 fpu_set_exception(pfpsd
, fp_inexact
);
407 if (pfpsd
->fp_current_exceptions
& (1 << fp_inexact
))
408 fpu_set_exception(pfpsd
, fp_underflow
);
409 if (pfpsd
->fp_fsrtem
& (1<<fp_underflow
)) {
410 fpu_set_exception(pfpsd
, fp_underflow
);
411 pfpsd
->fp_current_exceptions
&=
412 ~(1 << (int)fp_inexact
);
414 px
->significand
= pu
->significand
[0];
415 *py
= pu
->significand
[1];
416 *pz
= pu
->significand
[2];
417 *pw
= pu
->significand
[3];
420 round(pfpsd
, pu
); /* rounding overflow handled in round() */
421 if (pu
->exponent
>= 0x7fff) { /* overflow */
422 fpu_set_exception(pfpsd
, fp_overflow
);
423 fpu_set_exception(pfpsd
, fp_inexact
);
424 if (pfpsd
->fp_fsrtem
& (1<<fp_overflow
)) {
425 pfpsd
->fp_current_exceptions
&=
426 ~(1 << (int)fp_inexact
);
428 if (overflow_to_infinity(pfpsd
, pu
->sign
))
430 px
->exponent
= 0x7ffe; /* overflow to max norm */
431 px
->significand
= 0xffff;
437 px
->exponent
= pu
->exponent
;
438 px
->significand
= pu
->significand
[0];
439 *py
= pu
->significand
[1];
440 *pz
= pu
->significand
[2];
441 *pw
= pu
->significand
[3];
448 fp_simd_type
*pfpsd
, /* Pointer to simulator data */
449 unpacked
*pu
, /* unpacked operand */
450 uint_t n
, /* register where datum starts */
451 enum fp_op_type type
) /* type of datum */
459 packint32(pfpsd
, pu
, &x
);
460 if (!(pfpsd
->fp_current_exceptions
& pfpsd
->fp_fsrtem
))
461 pfpsd
->fp_current_write_freg(&x
, n
, pfpsd
);
468 packint64(pfpsd
, pu
, &x
);
469 if ((n
& 0x1) == 1) /* fix register encoding */
470 n
= (n
& 0x1e) | 0x20;
471 if (!(pfpsd
->fp_current_exceptions
& pfpsd
->fp_fsrtem
))
472 pfpsd
->fp_current_write_dreg(&x
, DOUBLE(n
), pfpsd
);
479 packsingle(pfpsd
, pu
, &x
);
480 if (!(pfpsd
->fp_current_exceptions
& pfpsd
->fp_fsrtem
))
481 pfpsd
->fp_current_write_freg(&x
, n
, pfpsd
);
492 packdouble(pfpsd
, pu
, &db
.x
[0], &db
.y
[1]);
493 if (!(pfpsd
->fp_current_exceptions
&
495 if ((n
& 0x1) == 1) /* fix register encoding */
496 n
= (n
& 0x1e) | 0x20;
497 pfpsd
->fp_current_write_dreg(&db
.ll
, DOUBLE(n
),
511 switch (pfpsd
->fp_precision
) {
521 packsingle(pfpsd
, pu
, &tx
);
523 unpacksingle(pfpsd
, pu
, tx
);
531 packdouble(pfpsd
, pu
, &tx
, &ty
);
533 unpackdouble(pfpsd
, pu
, tx
, ty
);
536 case fp_precision_3
: /* rounded to 64 bits */
538 k
= pu
->exponent
+ EXTENDED_BIAS
;
539 if (k
>= 0) k
= 113-64;
541 fpu_rightshift(pu
, 113-64);
543 pu
->sticky
= pu
->rounded
= 0;
549 packextended(pfpsd
, pu
, &ex
.x
, &ex
.y
[1],
551 if (!(pfpsd
->fp_current_exceptions
&
553 if ((n
& 0x1) == 1) /* fix register encoding */
554 n
= (n
& 0x1e) | 0x20;
555 pfpsd
->fp_current_write_dreg(&ex
.ll
[0],
557 pfpsd
->fp_current_write_dreg(&ex
.ll
[1],
568 fp_simd_type
*pfpsd
, /* Pointer to simulator data */
569 uint32_t *pu
, /* unpacked operand */
570 uint_t n
) /* register where datum starts */
572 pfpsd
->fp_current_write_freg(pu
, n
, pfpsd
);
577 fp_simd_type
*pfpsd
, /* Pointer to simulator data */
578 uint64_t *pu
, /* unpacked operand */
579 uint_t n
) /* register where datum starts */
581 if ((n
& 1) == 1) /* fix register encoding */
582 n
= (n
& 0x1e) | 0x20;
583 pfpsd
->fp_current_write_dreg(pu
, DOUBLE(n
), pfpsd
);