10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*3278Sgt29601 * Common Development and Distribution License (the "License").
6*3278Sgt29601 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
20132Srobinson */
21132Srobinson
22132Srobinson /*
231219Sraf * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
261219Sraf
270Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
280Sstevel@tonic-gate /* All Rights Reserved */
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate * Portions of this source code were derived from Berkeley
310Sstevel@tonic-gate * 4.3 BSD under license from the Regents of the University of
320Sstevel@tonic-gate * California.
330Sstevel@tonic-gate */
340Sstevel@tonic-gate
350Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
360Sstevel@tonic-gate
370Sstevel@tonic-gate /*
381219Sraf * Generic XDR routines impelmentation.
390Sstevel@tonic-gate *
400Sstevel@tonic-gate * These are the "floating point" xdr routines used to (de)serialize
410Sstevel@tonic-gate * most common data items. See xdr.h for more info on the interface to
420Sstevel@tonic-gate * xdr.
430Sstevel@tonic-gate */
440Sstevel@tonic-gate
451219Sraf #include "mt.h"
460Sstevel@tonic-gate #include <sys/types.h>
470Sstevel@tonic-gate #include <stdio.h>
480Sstevel@tonic-gate #include <rpc/types.h>
490Sstevel@tonic-gate #include <rpc/xdr.h>
500Sstevel@tonic-gate
510Sstevel@tonic-gate /*
520Sstevel@tonic-gate * This routine works on Suns, 3b2, 68000s, 386 and Vaxen in a manner
530Sstevel@tonic-gate * which is very efficient as bit twiddling is all that is needed. All
540Sstevel@tonic-gate * other machines can use this code but the code is inefficient as
550Sstevel@tonic-gate * various mathematical operations are used to generate the ieee format.
560Sstevel@tonic-gate * In addition rounding errors may occur due to the calculations involved.
570Sstevel@tonic-gate * To be most efficient, new machines should have their own ifdefs.
580Sstevel@tonic-gate * The encoding routines will fail if the machines try to encode a
590Sstevel@tonic-gate * float/double whose value can not be represented by the ieee format,
600Sstevel@tonic-gate * e.g. the exponent is too big/small.
610Sstevel@tonic-gate * ieee largest float = (2 ^ 128) * 0x1.fffff
620Sstevel@tonic-gate * ieee smallest float = (2 ^ -127) * 0x1.00000
630Sstevel@tonic-gate * ieee largest double = (2 ^ 1024) * 0x1.fffff
640Sstevel@tonic-gate * ieee smallest double = (2 ^ -1023) * 0x1.00000
650Sstevel@tonic-gate * The decoding routines assumes that the receiving machine can handle
660Sstevel@tonic-gate * floats/doubles as large/small as the values stated above. If you
670Sstevel@tonic-gate * use a machine which can not represent these values, you will need
680Sstevel@tonic-gate * to put ifdefs in the decode sections to identify areas of failure.
690Sstevel@tonic-gate */
700Sstevel@tonic-gate
710Sstevel@tonic-gate #if defined(vax)
720Sstevel@tonic-gate
730Sstevel@tonic-gate /*
740Sstevel@tonic-gate * What IEEE single precision floating point looks like this on a
750Sstevel@tonic-gate * vax.
760Sstevel@tonic-gate */
770Sstevel@tonic-gate
780Sstevel@tonic-gate struct ieee_single {
790Sstevel@tonic-gate unsigned int mantissa: 23;
800Sstevel@tonic-gate unsigned int exp : 8;
810Sstevel@tonic-gate unsigned int sign : 1;
820Sstevel@tonic-gate };
830Sstevel@tonic-gate
840Sstevel@tonic-gate #define IEEE_SNG_BIAS 0x7f
850Sstevel@tonic-gate #define VAX_SNG_BIAS 0x81
860Sstevel@tonic-gate
870Sstevel@tonic-gate
880Sstevel@tonic-gate /* Vax single precision floating point */
890Sstevel@tonic-gate struct vax_single {
900Sstevel@tonic-gate unsigned int mantissa1 : 7;
910Sstevel@tonic-gate unsigned int exp : 8;
920Sstevel@tonic-gate unsigned int sign : 1;
930Sstevel@tonic-gate unsigned int mantissa2 : 16;
940Sstevel@tonic-gate };
950Sstevel@tonic-gate
960Sstevel@tonic-gate #define VAX_SNG_BIAS 0x81
970Sstevel@tonic-gate
980Sstevel@tonic-gate static struct sgl_limits {
990Sstevel@tonic-gate struct vax_single s;
1000Sstevel@tonic-gate struct ieee_single ieee;
1010Sstevel@tonic-gate } sgl_limits[2] = {
1020Sstevel@tonic-gate {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */
1030Sstevel@tonic-gate { 0x0, 0xff, 0x0 }}, /* Max IEEE */
1040Sstevel@tonic-gate {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */
1050Sstevel@tonic-gate { 0x0, 0x0, 0x0 }} /* Min IEEE */
1060Sstevel@tonic-gate };
1070Sstevel@tonic-gate #endif /* vax */
1080Sstevel@tonic-gate
1090Sstevel@tonic-gate bool_t
xdr_float(XDR * xdrs,float * fp)1100Sstevel@tonic-gate xdr_float(XDR *xdrs, float *fp)
1110Sstevel@tonic-gate {
1120Sstevel@tonic-gate #if defined(vax)
1130Sstevel@tonic-gate struct ieee_single is;
1140Sstevel@tonic-gate struct vax_single vs, *vsp;
1150Sstevel@tonic-gate struct sgl_limits *lim;
1160Sstevel@tonic-gate size_t i;
1170Sstevel@tonic-gate #endif
1180Sstevel@tonic-gate
1190Sstevel@tonic-gate switch (xdrs->x_op) {
1200Sstevel@tonic-gate
1210Sstevel@tonic-gate case XDR_ENCODE:
1220Sstevel@tonic-gate #if defined(mc68000) || defined(sparc) || defined(u3b2) || \
123*3278Sgt29601 defined(u3b15) || defined(i386) || defined(amd64)
124132Srobinson return (XDR_PUTINT32(xdrs, (int *)fp));
1250Sstevel@tonic-gate #else
1260Sstevel@tonic-gate #if defined(vax)
1270Sstevel@tonic-gate vs = *((struct vax_single *)fp);
1280Sstevel@tonic-gate if ((vs.exp == 1) || (vs.exp == 2)) {
1290Sstevel@tonic-gate /* map these to subnormals */
1300Sstevel@tonic-gate is.exp = 0;
1310Sstevel@tonic-gate is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
1320Sstevel@tonic-gate /* lose some precision */
1330Sstevel@tonic-gate is.mantissa >>= 3 - vs.exp;
1340Sstevel@tonic-gate is.mantissa += (1 << (20 + vs.exp));
1350Sstevel@tonic-gate goto shipit;
1360Sstevel@tonic-gate }
1370Sstevel@tonic-gate for (i = 0, lim = sgl_limits;
1380Sstevel@tonic-gate i < (int)(sizeof (sgl_limits) /
1390Sstevel@tonic-gate sizeof (struct sgl_limits));
1400Sstevel@tonic-gate i++, lim++) {
1410Sstevel@tonic-gate if ((vs.mantissa2 == lim->s.mantissa2) &&
1420Sstevel@tonic-gate (vs.exp == lim->s.exp) &&
1430Sstevel@tonic-gate (vs.mantissa1 == lim->s.mantissa1)) {
1440Sstevel@tonic-gate is = lim->ieee;
1450Sstevel@tonic-gate goto shipit;
1460Sstevel@tonic-gate }
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
1490Sstevel@tonic-gate is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
1500Sstevel@tonic-gate shipit:
1510Sstevel@tonic-gate is.sign = vs.sign;
152132Srobinson return (XDR_PUTINT32(xdrs, (int32_t *)&is));
1530Sstevel@tonic-gate #else
1540Sstevel@tonic-gate {
1550Sstevel@tonic-gate /*
1560Sstevel@tonic-gate * Every machine can do this, its just not very efficient.
1570Sstevel@tonic-gate * In addtion, some rounding errors may occur do to the
1580Sstevel@tonic-gate * calculations involved.
1590Sstevel@tonic-gate */
1600Sstevel@tonic-gate float f;
1610Sstevel@tonic-gate int neg = 0;
1620Sstevel@tonic-gate int exp = 0;
1630Sstevel@tonic-gate int32_t val;
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate f = *fp;
1660Sstevel@tonic-gate if (f == 0) {
1670Sstevel@tonic-gate val = 0;
168132Srobinson return (XDR_PUTINT32(xdrs, &val));
1690Sstevel@tonic-gate }
1700Sstevel@tonic-gate if (f < 0) {
1710Sstevel@tonic-gate f = 0 - f;
1720Sstevel@tonic-gate neg = 1;
1730Sstevel@tonic-gate }
1740Sstevel@tonic-gate while (f < 1) {
1750Sstevel@tonic-gate f = f * 2;
1760Sstevel@tonic-gate --exp;
1770Sstevel@tonic-gate }
1780Sstevel@tonic-gate while (f >= 2) {
1790Sstevel@tonic-gate f = f/2;
1800Sstevel@tonic-gate ++exp;
1810Sstevel@tonic-gate }
1820Sstevel@tonic-gate if ((exp > 128) || (exp < -127)) {
1830Sstevel@tonic-gate /* over or under flowing ieee exponent */
1840Sstevel@tonic-gate return (FALSE);
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate val = neg;
1870Sstevel@tonic-gate val = val << 8; /* for the exponent */
1880Sstevel@tonic-gate val += 127 + exp; /* 127 is the bias */
1890Sstevel@tonic-gate val = val << 23; /* for the mantissa */
1900Sstevel@tonic-gate val += (int32_t)((f - 1) * 8388608); /* 2 ^ 23 */
191132Srobinson return (XDR_PUTINT32(xdrs, &val));
1920Sstevel@tonic-gate }
1930Sstevel@tonic-gate #endif
1940Sstevel@tonic-gate #endif
1950Sstevel@tonic-gate
1960Sstevel@tonic-gate case XDR_DECODE:
1970Sstevel@tonic-gate #if defined(mc68000) || defined(sparc) || defined(u3b2) || \
198*3278Sgt29601 defined(u3b15) || defined(i386) || defined(amd64)
199132Srobinson return (XDR_GETINT32(xdrs, (int *)fp));
2000Sstevel@tonic-gate #else
2010Sstevel@tonic-gate #if defined(vax)
2020Sstevel@tonic-gate vsp = (struct vax_single *)fp;
203132Srobinson if (!XDR_GETINT32(xdrs, (int32_t *)&is))
2040Sstevel@tonic-gate return (FALSE);
2050Sstevel@tonic-gate
2060Sstevel@tonic-gate for (i = 0, lim = sgl_limits;
2070Sstevel@tonic-gate i < (int)(sizeof (sgl_limits) /
2080Sstevel@tonic-gate sizeof (struct sgl_limits));
2090Sstevel@tonic-gate i++, lim++) {
2100Sstevel@tonic-gate if ((is.exp == lim->ieee.exp) &&
2110Sstevel@tonic-gate (is.mantissa == lim->ieee.mantissa)) {
2120Sstevel@tonic-gate *vsp = lim->s;
2130Sstevel@tonic-gate goto doneit;
2140Sstevel@tonic-gate } else if ((is.exp == 0) && (lim->ieee.exp == 0)) {
2150Sstevel@tonic-gate /* Special Case */
2160Sstevel@tonic-gate unsigned tmp = is.mantissa >> 20;
2170Sstevel@tonic-gate if (tmp >= 4) {
2180Sstevel@tonic-gate vsp->exp = 2;
2190Sstevel@tonic-gate } else if (tmp >= 2) {
2200Sstevel@tonic-gate vsp->exp = 1;
2210Sstevel@tonic-gate } else {
2220Sstevel@tonic-gate *vsp = min.s;
2230Sstevel@tonic-gate break;
2240Sstevel@tonic-gate } /* else */
2250Sstevel@tonic-gate tmp = is.mantissa - (1 << (20 + vsp->exp));
2260Sstevel@tonic-gate tmp <<= 3 - vsp->exp;
2270Sstevel@tonic-gate vsp->mantissa2 = tmp;
2280Sstevel@tonic-gate vsp->mantissa1 = (tmp >> 16);
2290Sstevel@tonic-gate goto doneit;
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
2320Sstevel@tonic-gate vsp->mantissa2 = is.mantissa;
2330Sstevel@tonic-gate vsp->mantissa1 = (is.mantissa >> 16);
2340Sstevel@tonic-gate doneit:
2350Sstevel@tonic-gate vsp->sign = is.sign;
2360Sstevel@tonic-gate return (TRUE);
2370Sstevel@tonic-gate #else
2380Sstevel@tonic-gate {
2390Sstevel@tonic-gate /*
2400Sstevel@tonic-gate * Every machine can do this, its just not very
2410Sstevel@tonic-gate * efficient. It assumes that the decoding machine's
2420Sstevel@tonic-gate * float can represent any value in the range of
2430Sstevel@tonic-gate * ieee largest float = (2 ^ 128) * 0x1.fffff
2440Sstevel@tonic-gate * to
2450Sstevel@tonic-gate * ieee smallest float = (2 ^ -127) * 0x1.00000
2460Sstevel@tonic-gate * In addtion, some rounding errors may occur do to the
2470Sstevel@tonic-gate * calculations involved.
2480Sstevel@tonic-gate */
2490Sstevel@tonic-gate float f;
2500Sstevel@tonic-gate int neg = 0;
2510Sstevel@tonic-gate int exp = 0;
2520Sstevel@tonic-gate int32_t val;
2530Sstevel@tonic-gate
254132Srobinson if (!XDR_GETINT32(xdrs, (int32_t *)&val))
2550Sstevel@tonic-gate return (FALSE);
2560Sstevel@tonic-gate neg = val & 0x80000000;
2570Sstevel@tonic-gate exp = (val & 0x7f800000) >> 23;
2580Sstevel@tonic-gate exp -= 127; /* subtract exponent base */
2590Sstevel@tonic-gate f = (val & 0x007fffff) * 0.00000011920928955078125;
2600Sstevel@tonic-gate /* 2 ^ -23 */
2610Sstevel@tonic-gate f++;
2620Sstevel@tonic-gate while (exp != 0) {
2630Sstevel@tonic-gate if (exp < 0) {
2640Sstevel@tonic-gate f = f/2.0;
2650Sstevel@tonic-gate ++exp;
2660Sstevel@tonic-gate } else {
2670Sstevel@tonic-gate f = f * 2.0;
2680Sstevel@tonic-gate --exp;
2690Sstevel@tonic-gate }
2700Sstevel@tonic-gate }
2710Sstevel@tonic-gate if (neg)
2720Sstevel@tonic-gate f = 0 - f;
2730Sstevel@tonic-gate *fp = f;
2740Sstevel@tonic-gate }
275132Srobinson return (TRUE);
2760Sstevel@tonic-gate #endif
2770Sstevel@tonic-gate #endif
2780Sstevel@tonic-gate
2790Sstevel@tonic-gate case XDR_FREE:
2800Sstevel@tonic-gate return (TRUE);
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate return (FALSE);
2830Sstevel@tonic-gate }
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate /*
2860Sstevel@tonic-gate * This routine works on Suns (Sky / 68000's) and Vaxen.
2870Sstevel@tonic-gate */
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate #if defined(vax)
2900Sstevel@tonic-gate /* What IEEE double precision floating point looks like on a Vax */
2910Sstevel@tonic-gate struct ieee_double {
2920Sstevel@tonic-gate unsigned int mantissa1 : 20;
2930Sstevel@tonic-gate unsigned int exp : 11;
2940Sstevel@tonic-gate unsigned int sign : 1;
2950Sstevel@tonic-gate unsigned int mantissa2 : 32;
2960Sstevel@tonic-gate };
2970Sstevel@tonic-gate
2980Sstevel@tonic-gate /* Vax double precision floating point */
2990Sstevel@tonic-gate struct vax_double {
3000Sstevel@tonic-gate unsigned int mantissa1 : 7;
3010Sstevel@tonic-gate unsigned int exp : 8;
3020Sstevel@tonic-gate unsigned int sign : 1;
3030Sstevel@tonic-gate unsigned int mantissa2 : 16;
3040Sstevel@tonic-gate unsigned int mantissa3 : 16;
3050Sstevel@tonic-gate unsigned int mantissa4 : 16;
3060Sstevel@tonic-gate };
3070Sstevel@tonic-gate
3080Sstevel@tonic-gate #define VAX_DBL_BIAS 0x81
3090Sstevel@tonic-gate #define IEEE_DBL_BIAS 0x3ff
3100Sstevel@tonic-gate #define MASK(nbits) ((1 << nbits) - 1)
3110Sstevel@tonic-gate
3120Sstevel@tonic-gate static struct dbl_limits {
3130Sstevel@tonic-gate struct vax_double d;
3140Sstevel@tonic-gate struct ieee_double ieee;
3150Sstevel@tonic-gate } dbl_limits[2] = {
3160Sstevel@tonic-gate {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */
3170Sstevel@tonic-gate { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */
3180Sstevel@tonic-gate {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */
3190Sstevel@tonic-gate { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */
3200Sstevel@tonic-gate };
3210Sstevel@tonic-gate
3220Sstevel@tonic-gate #endif /* vax */
3230Sstevel@tonic-gate
3240Sstevel@tonic-gate
3250Sstevel@tonic-gate bool_t
3260Sstevel@tonic-gate xdr_double(XDR *xdrs, double *dp)
3270Sstevel@tonic-gate {
328132Srobinson int *lp;
3290Sstevel@tonic-gate #if defined(vax)
3300Sstevel@tonic-gate struct ieee_double id;
3310Sstevel@tonic-gate struct vax_double vd;
332132Srobinson struct dbl_limits *lim;
3330Sstevel@tonic-gate size_t i;
3340Sstevel@tonic-gate #endif
3350Sstevel@tonic-gate
3360Sstevel@tonic-gate switch (xdrs->x_op) {
3370Sstevel@tonic-gate
3380Sstevel@tonic-gate case XDR_ENCODE:
3390Sstevel@tonic-gate #if defined(mc68000) || defined(u3b2) || defined(u3b15) || \
3400Sstevel@tonic-gate defined(_LONG_LONG_HTOL)
3410Sstevel@tonic-gate lp = (int *)dp;
342132Srobinson return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp));
3430Sstevel@tonic-gate #else
3440Sstevel@tonic-gate #if defined(_LONG_LONG_LTOH)
3450Sstevel@tonic-gate lp = (int *)dp;
3460Sstevel@tonic-gate lp++;
347132Srobinson return (XDR_PUTINT32(xdrs, lp--) && XDR_PUTINT32(xdrs, lp));
3480Sstevel@tonic-gate #else
3490Sstevel@tonic-gate #if defined(vax)
3500Sstevel@tonic-gate vd = *((struct vax_double *)dp);
3510Sstevel@tonic-gate for (i = 0, lim = dbl_limits;
3520Sstevel@tonic-gate i < (int)(sizeof (dbl_limits) /
3530Sstevel@tonic-gate sizeof (struct dbl_limits));
3540Sstevel@tonic-gate i++, lim++) {
3550Sstevel@tonic-gate if ((vd.mantissa4 == lim->d.mantissa4) &&
3560Sstevel@tonic-gate (vd.mantissa3 == lim->d.mantissa3) &&
3570Sstevel@tonic-gate (vd.mantissa2 == lim->d.mantissa2) &&
3580Sstevel@tonic-gate (vd.mantissa1 == lim->d.mantissa1) &&
3590Sstevel@tonic-gate (vd.exp == lim->d.exp)) {
3600Sstevel@tonic-gate id = lim->ieee;
3610Sstevel@tonic-gate goto shipit;
3620Sstevel@tonic-gate }
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
3650Sstevel@tonic-gate id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
3660Sstevel@tonic-gate id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
3670Sstevel@tonic-gate (vd.mantissa3 << 13) |
3680Sstevel@tonic-gate ((vd.mantissa4 >> 3) & MASK(13));
3690Sstevel@tonic-gate shipit:
3700Sstevel@tonic-gate id.sign = vd.sign;
3710Sstevel@tonic-gate lp = (int32_t *)&id;
3720Sstevel@tonic-gate #else
3730Sstevel@tonic-gate {
3740Sstevel@tonic-gate /*
3750Sstevel@tonic-gate * Every machine can do this, its just not very efficient.
3760Sstevel@tonic-gate * In addtion, some rounding errors may occur do to the
3770Sstevel@tonic-gate * calculations involved.
3780Sstevel@tonic-gate */
3790Sstevel@tonic-gate double d;
3800Sstevel@tonic-gate int neg = 0;
3810Sstevel@tonic-gate int exp = 0;
3820Sstevel@tonic-gate int32_t val[2];
3830Sstevel@tonic-gate
3840Sstevel@tonic-gate d = *dp;
3850Sstevel@tonic-gate if (d == 0) {
3860Sstevel@tonic-gate val[0] = 0;
3870Sstevel@tonic-gate val[1] = 0;
3880Sstevel@tonic-gate lp = val;
389132Srobinson return (XDR_PUTINT32(xdrs, lp++) &&
390132Srobinson XDR_PUTINT32(xdrs, lp));
3910Sstevel@tonic-gate }
3920Sstevel@tonic-gate if (d < 0) {
3930Sstevel@tonic-gate d = 0 - d;
3940Sstevel@tonic-gate neg = 1;
3950Sstevel@tonic-gate }
3960Sstevel@tonic-gate while (d < 1) {
3970Sstevel@tonic-gate d = d * 2;
3980Sstevel@tonic-gate --exp;
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate while (d >= 2) {
4010Sstevel@tonic-gate d = d/2;
4020Sstevel@tonic-gate ++exp;
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate if ((exp > 1024) || (exp < -1023)) {
4050Sstevel@tonic-gate /* over or under flowing ieee exponent */
4060Sstevel@tonic-gate return (FALSE);
4070Sstevel@tonic-gate }
4080Sstevel@tonic-gate val[0] = neg;
4090Sstevel@tonic-gate val[0] = val[0] << 11; /* for the exponent */
4100Sstevel@tonic-gate val[0] += 1023 + exp; /* 1023 is the bias */
4110Sstevel@tonic-gate val[0] = val[0] << 20; /* for the mantissa */
4120Sstevel@tonic-gate val[0] += (int32_t)((d - 1) * 1048576); /* 2 ^ 20 */
4130Sstevel@tonic-gate val[1] += (int32_t)((((d - 1) * 1048576) - val[0])
4140Sstevel@tonic-gate * 4294967296);
4150Sstevel@tonic-gate /* 2 ^ 32 */
4160Sstevel@tonic-gate lp = val;
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate #endif
419132Srobinson return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp));
4200Sstevel@tonic-gate #endif
4210Sstevel@tonic-gate #endif
4220Sstevel@tonic-gate
4230Sstevel@tonic-gate case XDR_DECODE:
4240Sstevel@tonic-gate #if defined(mc68000) || defined(u3b2) || defined(u3b15) || \
4250Sstevel@tonic-gate defined(_LONG_LONG_HTOL)
4260Sstevel@tonic-gate lp = (int *)dp;
427132Srobinson return (XDR_GETINT32(xdrs, lp++) && XDR_GETINT32(xdrs, lp));
4280Sstevel@tonic-gate #else
4290Sstevel@tonic-gate #if defined(_LONG_LONG_LTOH)
4300Sstevel@tonic-gate lp = (int *)dp;
4310Sstevel@tonic-gate lp++;
432132Srobinson return (XDR_GETINT32(xdrs, lp--) && XDR_GETINT32(xdrs, lp));
4330Sstevel@tonic-gate #else
4340Sstevel@tonic-gate #if defined(vax)
4350Sstevel@tonic-gate lp = (int32_t *)&id;
436132Srobinson if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp))
4370Sstevel@tonic-gate return (FALSE);
4380Sstevel@tonic-gate for (i = 0, lim = dbl_limits;
4390Sstevel@tonic-gate i < sizeof (dbl_limits)/sizeof (struct dbl_limits);
4400Sstevel@tonic-gate i++, lim++) {
4410Sstevel@tonic-gate if ((id.mantissa2 == lim->ieee.mantissa2) &&
4420Sstevel@tonic-gate (id.mantissa1 == lim->ieee.mantissa1) &&
4430Sstevel@tonic-gate (id.exp == lim->ieee.exp)) {
4440Sstevel@tonic-gate vd = lim->d;
4450Sstevel@tonic-gate goto doneit;
4460Sstevel@tonic-gate }
4470Sstevel@tonic-gate }
4480Sstevel@tonic-gate vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
4490Sstevel@tonic-gate vd.mantissa1 = (id.mantissa1 >> 13);
4500Sstevel@tonic-gate vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
4510Sstevel@tonic-gate (id.mantissa2 >> 29);
4520Sstevel@tonic-gate vd.mantissa3 = (id.mantissa2 >> 13);
4530Sstevel@tonic-gate vd.mantissa4 = (id.mantissa2 << 3);
4540Sstevel@tonic-gate doneit:
4550Sstevel@tonic-gate vd.sign = id.sign;
4560Sstevel@tonic-gate *dp = *((double *)&vd);
4570Sstevel@tonic-gate return (TRUE);
4580Sstevel@tonic-gate #else
4590Sstevel@tonic-gate {
4600Sstevel@tonic-gate /*
4610Sstevel@tonic-gate * Every machine can do this, its just not very
4620Sstevel@tonic-gate * efficient. It assumes that the decoding machine's
4630Sstevel@tonic-gate * double can represent any value in the range of
4640Sstevel@tonic-gate * ieee largest double = (2 ^ 1024) * 0x1.fffffffffffff
4650Sstevel@tonic-gate * to
4660Sstevel@tonic-gate * ieee smallest double = (2 ^ -1023) * 0x1.0000000000000
4670Sstevel@tonic-gate * In addtion, some rounding errors may occur do to the
4680Sstevel@tonic-gate * calculations involved.
4690Sstevel@tonic-gate */
4700Sstevel@tonic-gate double d;
4710Sstevel@tonic-gate int neg = 0;
4720Sstevel@tonic-gate int exp = 0;
4730Sstevel@tonic-gate int32_t val[2];
4740Sstevel@tonic-gate
4750Sstevel@tonic-gate lp = val;
476132Srobinson if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp))
4770Sstevel@tonic-gate return (FALSE);
4780Sstevel@tonic-gate neg = val[0] & 0x80000000;
4790Sstevel@tonic-gate exp = (val[0] & 0x7ff00000) >> 20;
4800Sstevel@tonic-gate exp -= 1023; /* subtract exponent base */
4810Sstevel@tonic-gate d = (val[0] & 0x000fffff) * 0.00000095367431640625;
4820Sstevel@tonic-gate /* 2 ^ -20 */
4830Sstevel@tonic-gate d += (val[1] * 0.0000000000000002220446049250313);
4840Sstevel@tonic-gate /* 2 ^ -52 */
4850Sstevel@tonic-gate d++;
4860Sstevel@tonic-gate while (exp != 0) {
4870Sstevel@tonic-gate if (exp < 0) {
4880Sstevel@tonic-gate d = d/2.0;
4890Sstevel@tonic-gate ++exp;
4900Sstevel@tonic-gate } else {
4910Sstevel@tonic-gate d = d * 2.0;
4920Sstevel@tonic-gate --exp;
4930Sstevel@tonic-gate }
4940Sstevel@tonic-gate }
4950Sstevel@tonic-gate if (neg)
4960Sstevel@tonic-gate d = 0 - d;
4970Sstevel@tonic-gate *dp = d;
4980Sstevel@tonic-gate }
4990Sstevel@tonic-gate #endif
5000Sstevel@tonic-gate #endif
5010Sstevel@tonic-gate #endif
5020Sstevel@tonic-gate
5030Sstevel@tonic-gate case XDR_FREE:
5040Sstevel@tonic-gate return (TRUE);
5050Sstevel@tonic-gate }
5060Sstevel@tonic-gate return (FALSE);
5070Sstevel@tonic-gate }
5080Sstevel@tonic-gate
509132Srobinson /* ARGSUSED */
5100Sstevel@tonic-gate bool_t
5110Sstevel@tonic-gate xdr_quadruple(XDR *xdrs, long double *fp)
5120Sstevel@tonic-gate {
5130Sstevel@tonic-gate /*
5140Sstevel@tonic-gate * The Sparc uses IEEE FP encoding, so just do a byte copy
5150Sstevel@tonic-gate */
5160Sstevel@tonic-gate
517132Srobinson #if !defined(sparc)
518132Srobinson return (FALSE);
519132Srobinson #else
5200Sstevel@tonic-gate switch (xdrs->x_op) {
5210Sstevel@tonic-gate case XDR_ENCODE:
522132Srobinson return (XDR_PUTBYTES(xdrs, (char *)fp, sizeof (long double)));
5230Sstevel@tonic-gate case XDR_DECODE:
524132Srobinson return (XDR_GETBYTES(xdrs, (char *)fp, sizeof (long double)));
525132Srobinson case XDR_FREE:
526132Srobinson return (TRUE);
527132Srobinson }
528132Srobinson return (FALSE);
5290Sstevel@tonic-gate #endif
5300Sstevel@tonic-gate }
531