xref: /onnv-gate/usr/src/lib/libnsl/rpc/xdr_float.c (revision 3278:cc172aafd1f4)
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