xdr_float.c revision 21062
11902Swollman/*
21902Swollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
31902Swollman * unrestricted use provided that this legend is included on all tape
41902Swollman * media and as a part of the software program in whole or part.  Users
51902Swollman * may copy or modify Sun RPC without charge, but are not authorized
61902Swollman * to license or distribute it to anyone else except as part of a product or
71902Swollman * program developed by the user.
88870Srgrimes *
91902Swollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
101902Swollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
111902Swollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
128870Srgrimes *
131902Swollman * Sun RPC is provided with no support and without any obligation on the
141902Swollman * part of Sun Microsystems, Inc. to assist in its use, correction,
151902Swollman * modification or enhancement.
168870Srgrimes *
171902Swollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
181902Swollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
191902Swollman * OR ANY PART THEREOF.
208870Srgrimes *
211902Swollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue
221902Swollman * or profits or other special, indirect and consequential damages, even if
231902Swollman * Sun has been advised of the possibility of such damages.
248870Srgrimes *
251902Swollman * Sun Microsystems, Inc.
261902Swollman * 2550 Garcia Avenue
271902Swollman * Mountain View, California  94043
281902Swollman */
291902Swollman
301902Swollman#if defined(LIBC_SCCS) && !defined(lint)
311902Swollman/*static char *sccsid = "from: @(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";*/
321902Swollman/*static char *sccsid = "from: @(#)xdr_float.c	2.1 88/07/29 4.0 RPCSRC";*/
3321062Speterstatic char *rcsid = "$Id: xdr_float.c,v 1.2 1995/05/30 05:42:04 rgrimes Exp $";
341902Swollman#endif
351902Swollman
361902Swollman/*
371902Swollman * xdr_float.c, Generic XDR routines impelmentation.
381902Swollman *
391902Swollman * Copyright (C) 1984, Sun Microsystems, Inc.
401902Swollman *
411902Swollman * These are the "floating point" xdr routines used to (de)serialize
421902Swollman * most common data items.  See xdr.h for more info on the interface to
431902Swollman * xdr.
441902Swollman */
451902Swollman
461902Swollman#include <stdio.h>
471902Swollman#include <sys/types.h>
481902Swollman#include <sys/param.h>
491902Swollman#include <rpc/types.h>
501902Swollman#include <rpc/xdr.h>
511902Swollman
521902Swollman/*
531902Swollman * NB: Not portable.
5421062Speter * This routine works on machines with IEEE754 FP and Vaxen.
551902Swollman */
561902Swollman
5721062Speter#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
5821062Speter    defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
5921062Speter    defined(__arm32__) || defined(__ppc__)
6021062Speter#include <machine/endian.h>
611902Swollman#define IEEEFP
621902Swollman#endif
631902Swollman
641902Swollman#ifdef vax
651902Swollman
661902Swollman/* What IEEE single precision floating point looks like on a Vax */
671902Swollmanstruct	ieee_single {
681902Swollman	unsigned int	mantissa: 23;
691902Swollman	unsigned int	exp     : 8;
701902Swollman	unsigned int	sign    : 1;
711902Swollman};
721902Swollman
731902Swollman/* Vax single precision floating point */
741902Swollmanstruct	vax_single {
751902Swollman	unsigned int	mantissa1 : 7;
761902Swollman	unsigned int	exp       : 8;
771902Swollman	unsigned int	sign      : 1;
781902Swollman	unsigned int	mantissa2 : 16;
791902Swollman};
801902Swollman
811902Swollman#define VAX_SNG_BIAS	0x81
821902Swollman#define IEEE_SNG_BIAS	0x7f
831902Swollman
841902Swollmanstatic struct sgl_limits {
851902Swollman	struct vax_single s;
861902Swollman	struct ieee_single ieee;
871902Swollman} sgl_limits[2] = {
881902Swollman	{{ 0x7f, 0xff, 0x0, 0xffff },	/* Max Vax */
891902Swollman	{ 0x0, 0xff, 0x0 }},		/* Max IEEE */
901902Swollman	{{ 0x0, 0x0, 0x0, 0x0 },	/* Min Vax */
911902Swollman	{ 0x0, 0x0, 0x0 }}		/* Min IEEE */
921902Swollman};
931902Swollman#endif /* vax */
941902Swollman
951902Swollmanbool_t
961902Swollmanxdr_float(xdrs, fp)
971902Swollman	register XDR *xdrs;
981902Swollman	register float *fp;
991902Swollman{
10021062Speter#ifdef IEEEFP
10121062Speter	bool_t rv;
10221062Speter	long tmpl;
10321062Speter#else
1041902Swollman	struct ieee_single is;
1051902Swollman	struct vax_single vs, *vsp;
1061902Swollman	struct sgl_limits *lim;
1071902Swollman	int i;
1081902Swollman#endif
1091902Swollman	switch (xdrs->x_op) {
1101902Swollman
1111902Swollman	case XDR_ENCODE:
1128870Srgrimes#ifdef IEEEFP
11321062Speter		tmpl = *(int32_t *)fp;
11421062Speter		return (XDR_PUTLONG(xdrs, &tmpl));
1151902Swollman#else
1161902Swollman		vs = *((struct vax_single *)fp);
1171902Swollman		for (i = 0, lim = sgl_limits;
1181902Swollman			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
1191902Swollman			i++, lim++) {
1201902Swollman			if ((vs.mantissa2 == lim->s.mantissa2) &&
1211902Swollman				(vs.exp == lim->s.exp) &&
1221902Swollman				(vs.mantissa1 == lim->s.mantissa1)) {
1231902Swollman				is = lim->ieee;
1241902Swollman				goto shipit;
1251902Swollman			}
1261902Swollman		}
1271902Swollman		is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
1281902Swollman		is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
1291902Swollman	shipit:
1301902Swollman		is.sign = vs.sign;
1311902Swollman		return (XDR_PUTLONG(xdrs, (long *)&is));
1321902Swollman#endif
1331902Swollman
1341902Swollman	case XDR_DECODE:
1351902Swollman#ifdef IEEEFP
13621062Speter		rv = XDR_GETLONG(xdrs, &tmpl);
13721062Speter		*(int32_t *)fp = tmpl;
13821062Speter		return (rv);
1391902Swollman#else
1401902Swollman		vsp = (struct vax_single *)fp;
1411902Swollman		if (!XDR_GETLONG(xdrs, (long *)&is))
1421902Swollman			return (FALSE);
1431902Swollman		for (i = 0, lim = sgl_limits;
1441902Swollman			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
1451902Swollman			i++, lim++) {
1461902Swollman			if ((is.exp == lim->ieee.exp) &&
1471902Swollman				(is.mantissa == lim->ieee.mantissa)) {
1481902Swollman				*vsp = lim->s;
1491902Swollman				goto doneit;
1501902Swollman			}
1511902Swollman		}
1521902Swollman		vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
1531902Swollman		vsp->mantissa2 = is.mantissa;
1541902Swollman		vsp->mantissa1 = (is.mantissa >> 16);
1551902Swollman	doneit:
1561902Swollman		vsp->sign = is.sign;
1571902Swollman		return (TRUE);
1581902Swollman#endif
1591902Swollman
1601902Swollman	case XDR_FREE:
1611902Swollman		return (TRUE);
1621902Swollman	}
1631902Swollman	return (FALSE);
1641902Swollman}
1651902Swollman
1661902Swollman#ifdef vax
1671902Swollman/* What IEEE double precision floating point looks like on a Vax */
1681902Swollmanstruct	ieee_double {
1691902Swollman	unsigned int	mantissa1 : 20;
1701902Swollman	unsigned int	exp       : 11;
1711902Swollman	unsigned int	sign      : 1;
1721902Swollman	unsigned int	mantissa2 : 32;
1731902Swollman};
1741902Swollman
1751902Swollman/* Vax double precision floating point */
1761902Swollmanstruct  vax_double {
1771902Swollman	unsigned int	mantissa1 : 7;
1781902Swollman	unsigned int	exp       : 8;
1791902Swollman	unsigned int	sign      : 1;
1801902Swollman	unsigned int	mantissa2 : 16;
1811902Swollman	unsigned int	mantissa3 : 16;
1821902Swollman	unsigned int	mantissa4 : 16;
1831902Swollman};
1841902Swollman
1851902Swollman#define VAX_DBL_BIAS	0x81
1861902Swollman#define IEEE_DBL_BIAS	0x3ff
1871902Swollman#define MASK(nbits)	((1 << nbits) - 1)
1881902Swollman
1891902Swollmanstatic struct dbl_limits {
1901902Swollman	struct	vax_double d;
1911902Swollman	struct	ieee_double ieee;
1921902Swollman} dbl_limits[2] = {
1931902Swollman	{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },	/* Max Vax */
1941902Swollman	{ 0x0, 0x7ff, 0x0, 0x0 }},			/* Max IEEE */
1951902Swollman	{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},		/* Min Vax */
1961902Swollman	{ 0x0, 0x0, 0x0, 0x0 }}				/* Min IEEE */
1971902Swollman};
1981902Swollman
1991902Swollman#endif /* vax */
2001902Swollman
2011902Swollman
2021902Swollmanbool_t
2031902Swollmanxdr_double(xdrs, dp)
2041902Swollman	register XDR *xdrs;
2051902Swollman	double *dp;
2061902Swollman{
20721062Speter#ifdef IEEEFP
20821062Speter	register int32_t *i32p;
20921062Speter	bool_t rv;
21021062Speter	long tmpl;
21121062Speter#else
2121902Swollman	register long *lp;
2131902Swollman	struct	ieee_double id;
2141902Swollman	struct	vax_double vd;
2151902Swollman	register struct dbl_limits *lim;
2161902Swollman	int i;
2171902Swollman#endif
2181902Swollman
2191902Swollman	switch (xdrs->x_op) {
2201902Swollman
2211902Swollman	case XDR_ENCODE:
2221902Swollman#ifdef IEEEFP
22321062Speter		i32p = (int32_t *)dp;
2241902Swollman#if BYTE_ORDER == BIG_ENDIAN
22521062Speter		tmpl = *i32p++;
22621062Speter		rv = XDR_PUTLONG(xdrs, &tmpl);
22721062Speter		if (!rv)
22821062Speter			return (rv);
22921062Speter		tmpl = *i32p;
23021062Speter		rv = XDR_PUTLONG(xdrs, &tmpl);
2311902Swollman#else
23221062Speter		tmpl = *(i32p+1);
23321062Speter		rv = XDR_PUTLONG(xdrs, &tmpl);
23421062Speter		if (!rv)
23521062Speter			return (rv);
23621062Speter		tmpl = *i32p;
23721062Speter		rv = XDR_PUTLONG(xdrs, &tmpl);
2381902Swollman#endif
23921062Speter		return (rv);
2401902Swollman#else
2411902Swollman		vd = *((struct vax_double *)dp);
2421902Swollman		for (i = 0, lim = dbl_limits;
2431902Swollman			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
2441902Swollman			i++, lim++) {
2451902Swollman			if ((vd.mantissa4 == lim->d.mantissa4) &&
2461902Swollman				(vd.mantissa3 == lim->d.mantissa3) &&
2471902Swollman				(vd.mantissa2 == lim->d.mantissa2) &&
2481902Swollman				(vd.mantissa1 == lim->d.mantissa1) &&
2491902Swollman				(vd.exp == lim->d.exp)) {
2501902Swollman				id = lim->ieee;
2511902Swollman				goto shipit;
2521902Swollman			}
2531902Swollman		}
2541902Swollman		id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
2551902Swollman		id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
2561902Swollman		id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
2571902Swollman				(vd.mantissa3 << 13) |
2581902Swollman				((vd.mantissa4 >> 3) & MASK(13));
2591902Swollman	shipit:
2601902Swollman		id.sign = vd.sign;
2611902Swollman		lp = (long *)&id;
2621902Swollman		return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
2631902Swollman#endif
2641902Swollman
2651902Swollman	case XDR_DECODE:
2661902Swollman#ifdef IEEEFP
26721062Speter		i32p = (int32_t *)dp;
2681902Swollman#if BYTE_ORDER == BIG_ENDIAN
26921062Speter		rv = XDR_GETLONG(xdrs, &tmpl);
27021062Speter		*i32p++ = tmpl;
27121062Speter		if (!rv)
27221062Speter			return (rv);
27321062Speter		rv = XDR_GETLONG(xdrs, &tmpl);
27421062Speter		*i32p = tmpl;
2751902Swollman#else
27621062Speter		rv = XDR_GETLONG(xdrs, &tmpl);
27721062Speter		*(i32p+1) = tmpl;
27821062Speter		if (!rv)
27921062Speter			return (rv);
28021062Speter		rv = XDR_GETLONG(xdrs, &tmpl);
28121062Speter		*i32p = tmpl;
2821902Swollman#endif
28321062Speter		return (rv);
2841902Swollman#else
2851902Swollman		lp = (long *)&id;
2861902Swollman		if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp))
2871902Swollman			return (FALSE);
2881902Swollman		for (i = 0, lim = dbl_limits;
2891902Swollman			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
2901902Swollman			i++, lim++) {
2911902Swollman			if ((id.mantissa2 == lim->ieee.mantissa2) &&
2921902Swollman				(id.mantissa1 == lim->ieee.mantissa1) &&
2931902Swollman				(id.exp == lim->ieee.exp)) {
2941902Swollman				vd = lim->d;
2951902Swollman				goto doneit;
2961902Swollman			}
2971902Swollman		}
2981902Swollman		vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
2991902Swollman		vd.mantissa1 = (id.mantissa1 >> 13);
3001902Swollman		vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
3011902Swollman				(id.mantissa2 >> 29);
3021902Swollman		vd.mantissa3 = (id.mantissa2 >> 13);
3031902Swollman		vd.mantissa4 = (id.mantissa2 << 3);
3041902Swollman	doneit:
3051902Swollman		vd.sign = id.sign;
3061902Swollman		*dp = *((double *)&vd);
3071902Swollman		return (TRUE);
3081902Swollman#endif
3091902Swollman
3101902Swollman	case XDR_FREE:
3111902Swollman		return (TRUE);
3121902Swollman	}
3131902Swollman	return (FALSE);
3141902Swollman}
315