/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ #pragma ident "%Z%%M% %I% %E% SMI" /* * Copyright (c) 1988 by Sun Microsystems, Inc. */ /* Unpack procedures for Sparc FPU simulator. */ #include "_Qquad.h" #include "_Qglobals.h" PRIVATE void unpackinteger(pu, x) unpacked *pu; /* unpacked result */ int x; /* packed integer */ { unsigned ux; pu->sticky = pu->rounded = 0; if (x == 0) { pu->sign = 0; pu->fpclass = fp_zero; } else { (*pu).sign = x < 0; (*pu).fpclass = fp_normal; (*pu).exponent = INTEGER_BIAS; if(x<0) ux = -x; else ux = x; (*pu).significand[0] = ux>>15; (*pu).significand[1] = (ux&0x7fff)<<17; (*pu).significand[2] = 0; (*pu).significand[3] = 0; fpu_normalize(pu); } } void unpacksingle(pu, x) unpacked *pu; /* unpacked result */ single_type x; /* packed single */ { unsigned u; pu->sticky = pu->rounded = 0; u = x.significand; (*pu).sign = x.sign; pu->significand[1] = 0; pu->significand[2] = 0; pu->significand[3] = 0; if (x.exponent == 0) { /* zero or sub */ if (x.significand == 0) { /* zero */ pu->fpclass = fp_zero; return; } else { /* subnormal */ pu->fpclass = fp_normal; pu->exponent = -SINGLE_BIAS-6; pu->significand[0]=u; fpu_normalize(pu); return; } } else if (x.exponent == 0xff) { /* inf or nan */ if (x.significand == 0) { /* inf */ pu->fpclass = fp_infinity; return; } else { /* nan */ if ((u & 0x400000) != 0) { /* quiet */ pu->fpclass = fp_quiet; } else {/* signaling */ pu->fpclass = fp_signaling; fpu_set_exception(fp_invalid); } pu->significand[0] = 0x18000 | (u >> 7); (*pu).significand[1]=((u&0x7f)<<25); return; } } (*pu).exponent = x.exponent - SINGLE_BIAS; (*pu).fpclass = fp_normal; (*pu).significand[0]=0x10000|(u>>7); (*pu).significand[1]=((u&0x7f)<<25); } void unpackdouble(pu, x, y) unpacked *pu; /* unpacked result */ double_type x; /* packed double */ unsigned y; { unsigned u; pu->sticky = pu->rounded = 0; u = x.significand; (*pu).sign = x.sign; pu->significand[1] = y; pu->significand[2] = 0; pu->significand[3] = 0; if (x.exponent == 0) { /* zero or sub */ if ((x.significand == 0) && (y == 0)) { /* zero */ pu->fpclass = fp_zero; return; } else { /* subnormal */ pu->fpclass = fp_normal; pu->exponent = -DOUBLE_BIAS-3; pu->significand[0] = u; fpu_normalize(pu); return; } } else if (x.exponent == 0x7ff) { /* inf or nan */ if ((u|y) == 0) { /* inf */ pu->fpclass = fp_infinity; return; } else { /* nan */ if ((u & 0x80000) != 0) { /* quiet */ pu->fpclass = fp_quiet; } else {/* signaling */ pu->fpclass = fp_signaling; fpu_set_exception(fp_invalid); } pu->significand[0] = 0x18000 | (u >> 4); (*pu).significand[1]=((u&0xf)<<28)|(y>>4); (*pu).significand[2]=((y&0xf)<<28); return; } } (*pu).exponent = x.exponent - DOUBLE_BIAS; (*pu).fpclass = fp_normal; (*pu).significand[0]=0x10000|(u>>4); (*pu).significand[1]=((u&0xf)<<28)|(y>>4); (*pu).significand[2]=((y&0xf)<<28); } PRIVATE void unpackextended(pu, x, y, z, w) unpacked *pu; /* unpacked result */ extended_type x; /* packed extended */ unsigned y, z, w; { unsigned u; pu->sticky = pu->rounded = 0; u = x.significand; (*pu).sign = x.sign; (*pu).fpclass = fp_normal; (*pu).exponent = x.exponent - EXTENDED_BIAS; (*pu).significand[0] = (x.exponent==0)? u:0x10000|u; (*pu).significand[1] = y; (*pu).significand[2] = z; (*pu).significand[3] = w; if (x.exponent < 0x7fff) { /* zero, normal, or subnormal */ if ((z|y|w|pu->significand[0]) == 0) { /* zero */ pu->fpclass = fp_zero; return; } else { /* normal or subnormal */ if(x.exponent==0) { fpu_normalize(pu); pu->exponent += 1; } return; } } else { /* inf or nan */ if ((u|z|y|w) == 0) { /* inf */ pu->fpclass = fp_infinity; return; } else { /* nan */ if ((u & 0x00008000) != 0) { /* quiet */ pu->fpclass = fp_quiet; } else {/* signaling */ pu->fpclass = fp_signaling; fpu_set_exception(fp_invalid); } pu->significand[0] |= 0x8000; /* make quiet */ return; } } } void _fp_unpack(pu, n, dtype) unpacked *pu; /* unpacked result */ int *n; /* input array */ enum fp_op_type dtype; /* type of datum */ { switch ((int) dtype) { case fp_op_integer: unpackinteger(pu, n[0]); break; case fp_op_single: { single_type x; *(int*)&x = n[0]; unpacksingle(pu, x); break; } case fp_op_double: { double_type x; double t=1.0; int i0,i1; if((*(int*)&t)!=0) {i0=0;i1=1;} else {i0=1;i1=0;} *(int*)&x = n[i0]; unpackdouble(pu, x, n[i1]); break; } case fp_op_extended: { extended_type x; double t=1.0; int i0,i1,i2,i3; if((*(int*)&t)!=0) {i0=0;i1=1;i2=2;i3=3;} else {i0=3;i1=2;i2=1;i3=0;} *(int*)&x = n[i0]; unpackextended(pu, x, n[i1], n[i2], n[i3]); break; } } }