xdr_float.c revision 298120
174462Salfred/*	$NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt Exp $	*/
274462Salfred
3259118Shrs/*-
4259118Shrs * Copyright (c) 2010, Oracle America, Inc.
58870Srgrimes *
6259118Shrs * Redistribution and use in source and binary forms, with or without
7259118Shrs * modification, are permitted provided that the following conditions are
8259118Shrs * met:
98870Srgrimes *
10259118Shrs *     * Redistributions of source code must retain the above copyright
11259118Shrs *       notice, this list of conditions and the following disclaimer.
12259118Shrs *     * Redistributions in binary form must reproduce the above
13259118Shrs *       copyright notice, this list of conditions and the following
14259118Shrs *       disclaimer in the documentation and/or other materials
15259118Shrs *       provided with the distribution.
16259118Shrs *     * Neither the name of the "Oracle America, Inc." nor the names of its
17259118Shrs *       contributors may be used to endorse or promote products derived
18259118Shrs *       from this software without specific prior written permission.
198870Srgrimes *
20259118Shrs *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21259118Shrs *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22259118Shrs *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23259118Shrs *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24259118Shrs *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25259118Shrs *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26259118Shrs *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27259118Shrs *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28259118Shrs *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29259118Shrs *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30259118Shrs *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31259118Shrs *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
321902Swollman */
331902Swollman
341902Swollman#if defined(LIBC_SCCS) && !defined(lint)
35136582Sobrienstatic char *sccsid2 = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
3674462Salfredstatic char *sccsid = "@(#)xdr_float.c	2.1 88/07/29 4.0 RPCSRC";
371902Swollman#endif
3892986Sobrien#include <sys/cdefs.h>
3992986Sobrien__FBSDID("$FreeBSD: head/lib/libc/xdr/xdr_float.c 298120 2016-04-16 17:52:00Z pfg $");
401902Swollman
411902Swollman/*
4274462Salfred * xdr_float.c, Generic XDR routines implementation.
431902Swollman *
441902Swollman * These are the "floating point" xdr routines used to (de)serialize
451902Swollman * most common data items.  See xdr.h for more info on the interface to
461902Swollman * xdr.
471902Swollman */
481902Swollman
4974462Salfred#include "namespace.h"
501902Swollman#include <sys/types.h>
511902Swollman#include <sys/param.h>
5274462Salfred
5374462Salfred#include <stdio.h>
5474462Salfred
551902Swollman#include <rpc/types.h>
561902Swollman#include <rpc/xdr.h>
5774462Salfred#include "un-namespace.h"
581902Swollman
591902Swollman/*
601902Swollman * NB: Not portable.
6121062Speter * This routine works on machines with IEEE754 FP and Vaxen.
621902Swollman */
631902Swollman
6421062Speter#include <machine/endian.h>
651902Swollman#define IEEEFP
661902Swollman
6774462Salfred#if defined(__vax__)
681902Swollman
691902Swollman/* What IEEE single precision floating point looks like on a Vax */
701902Swollmanstruct	ieee_single {
711902Swollman	unsigned int	mantissa: 23;
721902Swollman	unsigned int	exp     : 8;
731902Swollman	unsigned int	sign    : 1;
741902Swollman};
751902Swollman
761902Swollman/* Vax single precision floating point */
771902Swollmanstruct	vax_single {
781902Swollman	unsigned int	mantissa1 : 7;
791902Swollman	unsigned int	exp       : 8;
801902Swollman	unsigned int	sign      : 1;
811902Swollman	unsigned int	mantissa2 : 16;
821902Swollman};
831902Swollman
841902Swollman#define VAX_SNG_BIAS	0x81
851902Swollman#define IEEE_SNG_BIAS	0x7f
861902Swollman
871902Swollmanstatic struct sgl_limits {
881902Swollman	struct vax_single s;
891902Swollman	struct ieee_single ieee;
901902Swollman} sgl_limits[2] = {
911902Swollman	{{ 0x7f, 0xff, 0x0, 0xffff },	/* Max Vax */
921902Swollman	{ 0x0, 0xff, 0x0 }},		/* Max IEEE */
931902Swollman	{{ 0x0, 0x0, 0x0, 0x0 },	/* Min Vax */
941902Swollman	{ 0x0, 0x0, 0x0 }}		/* Min IEEE */
951902Swollman};
961902Swollman#endif /* vax */
971902Swollman
981902Swollmanbool_t
99288040Srodrigcxdr_float(XDR *xdrs, float *fp)
1001902Swollman{
10174462Salfred#ifndef IEEEFP
1021902Swollman	struct ieee_single is;
1031902Swollman	struct vax_single vs, *vsp;
1041902Swollman	struct sgl_limits *lim;
1051902Swollman	int i;
1061902Swollman#endif
1071902Swollman	switch (xdrs->x_op) {
1081902Swollman
1091902Swollman	case XDR_ENCODE:
1108870Srgrimes#ifdef IEEEFP
11174462Salfred		return (XDR_PUTINT32(xdrs, (int32_t *)fp));
1121902Swollman#else
1131902Swollman		vs = *((struct vax_single *)fp);
114298120Spfg		for (i = 0, lim = sgl_limits; i < nitems(sgl_limits);
115298120Spfg		    i++, lim++) {
1161902Swollman			if ((vs.mantissa2 == lim->s.mantissa2) &&
1171902Swollman				(vs.exp == lim->s.exp) &&
1181902Swollman				(vs.mantissa1 == lim->s.mantissa1)) {
1191902Swollman				is = lim->ieee;
1201902Swollman				goto shipit;
1211902Swollman			}
1221902Swollman		}
1231902Swollman		is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
1241902Swollman		is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
1251902Swollman	shipit:
1261902Swollman		is.sign = vs.sign;
12774462Salfred		return (XDR_PUTINT32(xdrs, (int32_t *)&is));
1281902Swollman#endif
1291902Swollman
1301902Swollman	case XDR_DECODE:
1311902Swollman#ifdef IEEEFP
13274462Salfred		return (XDR_GETINT32(xdrs, (int32_t *)fp));
1331902Swollman#else
1341902Swollman		vsp = (struct vax_single *)fp;
13574462Salfred		if (!XDR_GETINT32(xdrs, (int32_t *)&is))
1361902Swollman			return (FALSE);
137298120Spfg		for (i = 0, lim = sgl_limits; i < nitems(sgl_limits);
138298120Spfg		    i++, lim++) {
1391902Swollman			if ((is.exp == lim->ieee.exp) &&
1401902Swollman				(is.mantissa == lim->ieee.mantissa)) {
1411902Swollman				*vsp = lim->s;
1421902Swollman				goto doneit;
1431902Swollman			}
1441902Swollman		}
1451902Swollman		vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
1461902Swollman		vsp->mantissa2 = is.mantissa;
1471902Swollman		vsp->mantissa1 = (is.mantissa >> 16);
1481902Swollman	doneit:
1491902Swollman		vsp->sign = is.sign;
1501902Swollman		return (TRUE);
1511902Swollman#endif
1521902Swollman
1531902Swollman	case XDR_FREE:
1541902Swollman		return (TRUE);
1551902Swollman	}
15674462Salfred	/* NOTREACHED */
1571902Swollman	return (FALSE);
1581902Swollman}
1591902Swollman
16074462Salfred#if defined(__vax__)
1611902Swollman/* What IEEE double precision floating point looks like on a Vax */
1621902Swollmanstruct	ieee_double {
1631902Swollman	unsigned int	mantissa1 : 20;
1641902Swollman	unsigned int	exp       : 11;
1651902Swollman	unsigned int	sign      : 1;
1661902Swollman	unsigned int	mantissa2 : 32;
1671902Swollman};
1681902Swollman
1691902Swollman/* Vax double precision floating point */
1701902Swollmanstruct  vax_double {
1711902Swollman	unsigned int	mantissa1 : 7;
1721902Swollman	unsigned int	exp       : 8;
1731902Swollman	unsigned int	sign      : 1;
1741902Swollman	unsigned int	mantissa2 : 16;
1751902Swollman	unsigned int	mantissa3 : 16;
1761902Swollman	unsigned int	mantissa4 : 16;
1771902Swollman};
1781902Swollman
1791902Swollman#define VAX_DBL_BIAS	0x81
1801902Swollman#define IEEE_DBL_BIAS	0x3ff
1811902Swollman#define MASK(nbits)	((1 << nbits) - 1)
1821902Swollman
1831902Swollmanstatic struct dbl_limits {
1841902Swollman	struct	vax_double d;
1851902Swollman	struct	ieee_double ieee;
1861902Swollman} dbl_limits[2] = {
1871902Swollman	{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },	/* Max Vax */
1881902Swollman	{ 0x0, 0x7ff, 0x0, 0x0 }},			/* Max IEEE */
1891902Swollman	{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},		/* Min Vax */
1901902Swollman	{ 0x0, 0x0, 0x0, 0x0 }}				/* Min IEEE */
1911902Swollman};
1921902Swollman
1931902Swollman#endif /* vax */
1941902Swollman
1951902Swollman
1961902Swollmanbool_t
197283833Srodrigcxdr_double(XDR *xdrs, double *dp)
1981902Swollman{
19921062Speter#ifdef IEEEFP
20074462Salfred	int32_t *i32p;
20121062Speter	bool_t rv;
20221062Speter#else
20374462Salfred	int32_t *lp;
2041902Swollman	struct	ieee_double id;
2051902Swollman	struct	vax_double vd;
20674462Salfred	struct dbl_limits *lim;
2071902Swollman	int i;
2081902Swollman#endif
2091902Swollman
2101902Swollman	switch (xdrs->x_op) {
2111902Swollman
2121902Swollman	case XDR_ENCODE:
2131902Swollman#ifdef IEEEFP
21474462Salfred		i32p = (int32_t *)(void *)dp;
2151902Swollman#if BYTE_ORDER == BIG_ENDIAN
21674462Salfred		rv = XDR_PUTINT32(xdrs, i32p);
21721062Speter		if (!rv)
21821062Speter			return (rv);
21974462Salfred		rv = XDR_PUTINT32(xdrs, i32p+1);
2201902Swollman#else
22174462Salfred		rv = XDR_PUTINT32(xdrs, i32p+1);
22221062Speter		if (!rv)
22321062Speter			return (rv);
22474462Salfred		rv = XDR_PUTINT32(xdrs, i32p);
2251902Swollman#endif
22621062Speter		return (rv);
2271902Swollman#else
2281902Swollman		vd = *((struct vax_double *)dp);
229298120Spfg		for (i = 0, lim = dbl_limits; i < nitems(dbl_limits);
230298120Spfg		    i++, lim++) {
2311902Swollman			if ((vd.mantissa4 == lim->d.mantissa4) &&
2321902Swollman				(vd.mantissa3 == lim->d.mantissa3) &&
2331902Swollman				(vd.mantissa2 == lim->d.mantissa2) &&
2341902Swollman				(vd.mantissa1 == lim->d.mantissa1) &&
2351902Swollman				(vd.exp == lim->d.exp)) {
2361902Swollman				id = lim->ieee;
2371902Swollman				goto shipit;
2381902Swollman			}
2391902Swollman		}
2401902Swollman		id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
2411902Swollman		id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
2421902Swollman		id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
2431902Swollman				(vd.mantissa3 << 13) |
2441902Swollman				((vd.mantissa4 >> 3) & MASK(13));
2451902Swollman	shipit:
2461902Swollman		id.sign = vd.sign;
24774462Salfred		lp = (int32_t *)&id;
24874462Salfred		return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp));
2491902Swollman#endif
2501902Swollman
2511902Swollman	case XDR_DECODE:
2521902Swollman#ifdef IEEEFP
25374462Salfred		i32p = (int32_t *)(void *)dp;
2541902Swollman#if BYTE_ORDER == BIG_ENDIAN
25574462Salfred		rv = XDR_GETINT32(xdrs, i32p);
25621062Speter		if (!rv)
25721062Speter			return (rv);
25874462Salfred		rv = XDR_GETINT32(xdrs, i32p+1);
2591902Swollman#else
26074462Salfred		rv = XDR_GETINT32(xdrs, i32p+1);
26121062Speter		if (!rv)
26221062Speter			return (rv);
26374462Salfred		rv = XDR_GETINT32(xdrs, i32p);
2641902Swollman#endif
26521062Speter		return (rv);
2661902Swollman#else
26774462Salfred		lp = (int32_t *)&id;
26874462Salfred		if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp))
2691902Swollman			return (FALSE);
270298120Spfg		for (i = 0, lim = dbl_limits; i < nitems(dbl_limits);
271298120Spfg		    i++, lim++) {
2721902Swollman			if ((id.mantissa2 == lim->ieee.mantissa2) &&
2731902Swollman				(id.mantissa1 == lim->ieee.mantissa1) &&
2741902Swollman				(id.exp == lim->ieee.exp)) {
2751902Swollman				vd = lim->d;
2761902Swollman				goto doneit;
2771902Swollman			}
2781902Swollman		}
2791902Swollman		vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
2801902Swollman		vd.mantissa1 = (id.mantissa1 >> 13);
2811902Swollman		vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
2821902Swollman				(id.mantissa2 >> 29);
2831902Swollman		vd.mantissa3 = (id.mantissa2 >> 13);
2841902Swollman		vd.mantissa4 = (id.mantissa2 << 3);
2851902Swollman	doneit:
2861902Swollman		vd.sign = id.sign;
2871902Swollman		*dp = *((double *)&vd);
2881902Swollman		return (TRUE);
2891902Swollman#endif
2901902Swollman
2911902Swollman	case XDR_FREE:
2921902Swollman		return (TRUE);
2931902Swollman	}
29474462Salfred	/* NOTREACHED */
2951902Swollman	return (FALSE);
2961902Swollman}
297