Files
Arquivotheca.SunOS-4.1.4/lib/libc/gen/common/_Qfunpack.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

213 lines
4.9 KiB
C

#ifdef sccsid
static char sccsid[] = "@(#)_Qfunpack.c 1.1 94/10/31 Copyr 1987 Sun Micro";
#endif
/*
* 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;
}
}
}