Blame sunrpc/xdr_float.c

Packit 6c4009
/*
Packit 6c4009
 * xdr_float.c, Generic XDR routines implementation.
Packit 6c4009
 *
Packit 6c4009
 * Copyright (c) 2010, Oracle America, Inc.
Packit 6c4009
 *
Packit 6c4009
 * Redistribution and use in source and binary forms, with or without
Packit 6c4009
 * modification, are permitted provided that the following conditions are
Packit 6c4009
 * met:
Packit 6c4009
 *
Packit 6c4009
 *     * Redistributions of source code must retain the above copyright
Packit 6c4009
 *       notice, this list of conditions and the following disclaimer.
Packit 6c4009
 *     * Redistributions in binary form must reproduce the above
Packit 6c4009
 *       copyright notice, this list of conditions and the following
Packit 6c4009
 *       disclaimer in the documentation and/or other materials
Packit 6c4009
 *       provided with the distribution.
Packit 6c4009
 *     * Neither the name of the "Oracle America, Inc." nor the names of its
Packit 6c4009
 *       contributors may be used to endorse or promote products derived
Packit 6c4009
 *       from this software without specific prior written permission.
Packit 6c4009
 *
Packit 6c4009
 *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 6c4009
 *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 6c4009
 *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
Packit 6c4009
 *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
Packit 6c4009
 *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
Packit 6c4009
 *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 6c4009
 *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
Packit 6c4009
 *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
Packit 6c4009
 *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
Packit 6c4009
 *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Packit 6c4009
 *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 6c4009
 *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 6c4009
 *
Packit 6c4009
 * These are the "floating point" xdr routines used to (de)serialize
Packit 6c4009
 * most common data items.  See xdr.h for more info on the interface to
Packit 6c4009
 * xdr.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <endian.h>
Packit 6c4009
Packit 6c4009
#include <rpc/types.h>
Packit 6c4009
#include <rpc/xdr.h>
Packit 6c4009
#include <shlib-compat.h>
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * NB: Not portable.
Packit 6c4009
 * This routine works on Suns (Sky / 68000's) and Vaxen.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
#define LSW	(__FLOAT_WORD_ORDER == __BIG_ENDIAN)
Packit 6c4009
Packit 6c4009
#ifdef vax
Packit 6c4009
Packit 6c4009
/* What IEEE single precision floating point looks like on a Vax */
Packit 6c4009
struct	ieee_single {
Packit 6c4009
	unsigned int	mantissa: 23;
Packit 6c4009
	unsigned int	exp     : 8;
Packit 6c4009
	unsigned int	sign    : 1;
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* Vax single precision floating point */
Packit 6c4009
struct	vax_single {
Packit 6c4009
	unsigned int	mantissa1 : 7;
Packit 6c4009
	unsigned int	exp       : 8;
Packit 6c4009
	unsigned int	sign      : 1;
Packit 6c4009
	unsigned int	mantissa2 : 16;
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
#define VAX_SNG_BIAS	0x81
Packit 6c4009
#define IEEE_SNG_BIAS	0x7f
Packit 6c4009
Packit 6c4009
static struct sgl_limits {
Packit 6c4009
	struct vax_single s;
Packit 6c4009
	struct ieee_single ieee;
Packit 6c4009
} sgl_limits[2] = {
Packit 6c4009
	{{ 0x7f, 0xff, 0x0, 0xffff },	/* Max Vax */
Packit 6c4009
	{ 0x0, 0xff, 0x0 }},		/* Max IEEE */
Packit 6c4009
	{{ 0x0, 0x0, 0x0, 0x0 },	/* Min Vax */
Packit 6c4009
	{ 0x0, 0x0, 0x0 }}		/* Min IEEE */
Packit 6c4009
};
Packit 6c4009
#endif /* vax */
Packit 6c4009
Packit 6c4009
bool_t
Packit 6c4009
xdr_float (XDR *xdrs, float *fp)
Packit 6c4009
{
Packit 6c4009
#ifdef vax
Packit 6c4009
	struct ieee_single is;
Packit 6c4009
	struct vax_single vs, *vsp;
Packit 6c4009
	struct sgl_limits *lim;
Packit 6c4009
	int i;
Packit 6c4009
#endif
Packit 6c4009
	switch (xdrs->x_op) {
Packit 6c4009
Packit 6c4009
	case XDR_ENCODE:
Packit 6c4009
#ifdef vax
Packit 6c4009
		vs = *((struct vax_single *)fp);
Packit 6c4009
		for (i = 0, lim = sgl_limits;
Packit 6c4009
			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
Packit 6c4009
			i++, lim++) {
Packit 6c4009
			if ((vs.mantissa2 == lim->s.mantissa2) &&
Packit 6c4009
				(vs.exp == lim->s.exp) &&
Packit 6c4009
				(vs.mantissa1 == lim->s.mantissa1)) {
Packit 6c4009
				is = lim->ieee;
Packit 6c4009
				goto shipit;
Packit 6c4009
			}
Packit 6c4009
		}
Packit 6c4009
		is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
Packit 6c4009
		is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
Packit 6c4009
	shipit:
Packit 6c4009
		is.sign = vs.sign;
Packit 6c4009
		return (XDR_PUTLONG(xdrs, (long *)&is);;
Packit 6c4009
#else
Packit 6c4009
		if (sizeof(float) == sizeof(long))
Packit 6c4009
			return (XDR_PUTLONG(xdrs, (long *)fp));
Packit 6c4009
		else if (sizeof(float) == sizeof(int)) {
Packit 6c4009
			long tmp = *(int *)fp;
Packit 6c4009
			return (XDR_PUTLONG(xdrs, &tmp));
Packit 6c4009
		}
Packit 6c4009
		break;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
	case XDR_DECODE:
Packit 6c4009
#ifdef vax
Packit 6c4009
		vsp = (struct vax_single *)fp;
Packit 6c4009
		if (!XDR_GETLONG(xdrs, (long *)&is))
Packit 6c4009
			return (FALSE);
Packit 6c4009
		for (i = 0, lim = sgl_limits;
Packit 6c4009
			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
Packit 6c4009
			i++, lim++) {
Packit 6c4009
			if ((is.exp == lim->ieee.exp) &&
Packit 6c4009
				(is.mantissa == lim->ieee.mantissa)) {
Packit 6c4009
				*vsp = lim->s;
Packit 6c4009
				goto doneit;
Packit 6c4009
			}
Packit 6c4009
		}
Packit 6c4009
		vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
Packit 6c4009
		vsp->mantissa2 = is.mantissa;
Packit 6c4009
		vsp->mantissa1 = (is.mantissa >> 16);
Packit 6c4009
	doneit:
Packit 6c4009
		vsp->sign = is.sign;
Packit 6c4009
		return (TRUE);
Packit 6c4009
#else
Packit 6c4009
		if (sizeof(float) == sizeof(long))
Packit 6c4009
			return (XDR_GETLONG(xdrs, (long *)fp));
Packit 6c4009
		else if (sizeof(float) == sizeof(int)) {
Packit 6c4009
			long tmp;
Packit 6c4009
			if (XDR_GETLONG(xdrs, &tmp)) {
Packit 6c4009
				*(int *)fp = tmp;
Packit 6c4009
				return (TRUE);
Packit 6c4009
			}
Packit 6c4009
		}
Packit 6c4009
		break;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
	case XDR_FREE:
Packit 6c4009
		return (TRUE);
Packit 6c4009
	}
Packit 6c4009
	return (FALSE);
Packit 6c4009
}
Packit 6c4009
libc_hidden_nolink_sunrpc (xdr_float, GLIBC_2_0)
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * This routine works on Suns (Sky / 68000's) and Vaxen.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
#ifdef vax
Packit 6c4009
/* What IEEE double precision floating point looks like on a Vax */
Packit 6c4009
struct	ieee_double {
Packit 6c4009
	unsigned int	mantissa1 : 20;
Packit 6c4009
	unsigned int	exp       : 11;
Packit 6c4009
	unsigned int	sign      : 1;
Packit 6c4009
	unsigned int	mantissa2 : 32;
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
/* Vax double precision floating point */
Packit 6c4009
struct  vax_double {
Packit 6c4009
	unsigned int	mantissa1 : 7;
Packit 6c4009
	unsigned int	exp       : 8;
Packit 6c4009
	unsigned int	sign      : 1;
Packit 6c4009
	unsigned int	mantissa2 : 16;
Packit 6c4009
	unsigned int	mantissa3 : 16;
Packit 6c4009
	unsigned int	mantissa4 : 16;
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
#define VAX_DBL_BIAS	0x81
Packit 6c4009
#define IEEE_DBL_BIAS	0x3ff
Packit 6c4009
#define MASK(nbits)	((1 << nbits) - 1)
Packit 6c4009
Packit 6c4009
static struct dbl_limits {
Packit 6c4009
	struct	vax_double d;
Packit 6c4009
	struct	ieee_double ieee;
Packit 6c4009
} dbl_limits[2] = {
Packit 6c4009
	{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },	/* Max Vax */
Packit 6c4009
	{ 0x0, 0x7ff, 0x0, 0x0 }},			/* Max IEEE */
Packit 6c4009
	{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},		/* Min Vax */
Packit 6c4009
	{ 0x0, 0x0, 0x0, 0x0 }}				/* Min IEEE */
Packit 6c4009
};
Packit 6c4009
Packit 6c4009
#endif /* vax */
Packit 6c4009
Packit 6c4009
Packit 6c4009
bool_t
Packit 6c4009
xdr_double (XDR *xdrs, double *dp)
Packit 6c4009
{
Packit 6c4009
#ifdef vax
Packit 6c4009
	struct	ieee_double id;
Packit 6c4009
	struct	vax_double vd;
Packit 6c4009
	register struct dbl_limits *lim;
Packit 6c4009
	int i;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
	switch (xdrs->x_op) {
Packit 6c4009
Packit 6c4009
	case XDR_ENCODE:
Packit 6c4009
#ifdef vax
Packit 6c4009
		vd = *((struct vax_double *)dp);
Packit 6c4009
		for (i = 0, lim = dbl_limits;
Packit 6c4009
			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
Packit 6c4009
			i++, lim++) {
Packit 6c4009
			if ((vd.mantissa4 == lim->d.mantissa4) &&
Packit 6c4009
				(vd.mantissa3 == lim->d.mantissa3) &&
Packit 6c4009
				(vd.mantissa2 == lim->d.mantissa2) &&
Packit 6c4009
				(vd.mantissa1 == lim->d.mantissa1) &&
Packit 6c4009
				(vd.exp == lim->d.exp)) {
Packit 6c4009
				id = lim->ieee;
Packit 6c4009
				goto shipit;
Packit 6c4009
			}
Packit 6c4009
		}
Packit 6c4009
		id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
Packit 6c4009
		id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
Packit 6c4009
		id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
Packit 6c4009
				(vd.mantissa3 << 13) |
Packit 6c4009
				((vd.mantissa4 >> 3) & MASK(13));
Packit 6c4009
	shipit:
Packit 6c4009
		id.sign = vd.sign;
Packit 6c4009
		dp = (double *)&id;
Packit 6c4009
#endif
Packit 6c4009
		if (2*sizeof(long) == sizeof(double)) {
Packit 6c4009
			long *lp = (long *)dp;
Packit 6c4009
			return (XDR_PUTLONG(xdrs, lp+!LSW) &&
Packit 6c4009
				XDR_PUTLONG(xdrs, lp+LSW));
Packit 6c4009
		} else if (2*sizeof(int) == sizeof(double)) {
Packit 6c4009
			int *ip = (int *)dp;
Packit 6c4009
			long tmp[2];
Packit 6c4009
			tmp[0] = ip[!LSW];
Packit 6c4009
			tmp[1] = ip[LSW];
Packit 6c4009
			return (XDR_PUTLONG(xdrs, tmp) &&
Packit 6c4009
				XDR_PUTLONG(xdrs, tmp+1));
Packit 6c4009
		}
Packit 6c4009
		break;
Packit 6c4009
Packit 6c4009
	case XDR_DECODE:
Packit 6c4009
#ifdef vax
Packit 6c4009
		lp = (long *)&id;
Packit 6c4009
		if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp))
Packit 6c4009
			return (FALSE);
Packit 6c4009
		for (i = 0, lim = dbl_limits;
Packit 6c4009
			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
Packit 6c4009
			i++, lim++) {
Packit 6c4009
			if ((id.mantissa2 == lim->ieee.mantissa2) &&
Packit 6c4009
				(id.mantissa1 == lim->ieee.mantissa1) &&
Packit 6c4009
				(id.exp == lim->ieee.exp)) {
Packit 6c4009
				vd = lim->d;
Packit 6c4009
				goto doneit;
Packit 6c4009
			}
Packit 6c4009
		}
Packit 6c4009
		vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
Packit 6c4009
		vd.mantissa1 = (id.mantissa1 >> 13);
Packit 6c4009
		vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
Packit 6c4009
				(id.mantissa2 >> 29);
Packit 6c4009
		vd.mantissa3 = (id.mantissa2 >> 13);
Packit 6c4009
		vd.mantissa4 = (id.mantissa2 << 3);
Packit 6c4009
	doneit:
Packit 6c4009
		vd.sign = id.sign;
Packit 6c4009
		*dp = *((double *)&vd);
Packit 6c4009
		return (TRUE);
Packit 6c4009
#else
Packit 6c4009
		if (2*sizeof(long) == sizeof(double)) {
Packit 6c4009
			long *lp = (long *)dp;
Packit 6c4009
			return (XDR_GETLONG(xdrs, lp+!LSW) &&
Packit 6c4009
				XDR_GETLONG(xdrs, lp+LSW));
Packit 6c4009
		} else if (2*sizeof(int) == sizeof(double)) {
Packit 6c4009
			int *ip = (int *)dp;
Packit 6c4009
			long tmp[2];
Packit 6c4009
			if (XDR_GETLONG(xdrs, tmp+!LSW) &&
Packit 6c4009
			    XDR_GETLONG(xdrs, tmp+LSW)) {
Packit 6c4009
				ip[0] = tmp[0];
Packit 6c4009
				ip[1] = tmp[1];
Packit 6c4009
				return (TRUE);
Packit 6c4009
			}
Packit 6c4009
		}
Packit 6c4009
		break;
Packit 6c4009
#endif
Packit 6c4009
Packit 6c4009
	case XDR_FREE:
Packit 6c4009
		return (TRUE);
Packit 6c4009
	}
Packit 6c4009
	return (FALSE);
Packit 6c4009
}
Packit 6c4009
libc_hidden_nolink_sunrpc (xdr_double, GLIBC_2_0)