1*0a6a1f1dSLionel Sambuc /* $NetBSD: xdr_float.c,v 1.40 2014/08/24 17:07:00 matt Exp $ */
22fe8fb19SBen Gras
32fe8fb19SBen Gras /*
484d9c625SLionel Sambuc * Copyright (c) 2010, Oracle America, Inc.
52fe8fb19SBen Gras *
684d9c625SLionel Sambuc * Redistribution and use in source and binary forms, with or without
784d9c625SLionel Sambuc * modification, are permitted provided that the following conditions are
884d9c625SLionel Sambuc * met:
92fe8fb19SBen Gras *
1084d9c625SLionel Sambuc * * Redistributions of source code must retain the above copyright
1184d9c625SLionel Sambuc * notice, this list of conditions and the following disclaimer.
1284d9c625SLionel Sambuc * * Redistributions in binary form must reproduce the above
1384d9c625SLionel Sambuc * copyright notice, this list of conditions and the following
1484d9c625SLionel Sambuc * disclaimer in the documentation and/or other materials
1584d9c625SLionel Sambuc * provided with the distribution.
1684d9c625SLionel Sambuc * * Neither the name of the "Oracle America, Inc." nor the names of its
1784d9c625SLionel Sambuc * contributors may be used to endorse or promote products derived
1884d9c625SLionel Sambuc * from this software without specific prior written permission.
192fe8fb19SBen Gras *
2084d9c625SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2184d9c625SLionel Sambuc * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2284d9c625SLionel Sambuc * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2384d9c625SLionel Sambuc * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
2484d9c625SLionel Sambuc * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
2584d9c625SLionel Sambuc * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2684d9c625SLionel Sambuc * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
2784d9c625SLionel Sambuc * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2884d9c625SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
2984d9c625SLionel Sambuc * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3084d9c625SLionel Sambuc * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3184d9c625SLionel Sambuc * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
322fe8fb19SBen Gras */
332fe8fb19SBen Gras
342fe8fb19SBen Gras #include <sys/cdefs.h>
352fe8fb19SBen Gras #if defined(LIBC_SCCS) && !defined(lint)
362fe8fb19SBen Gras #if 0
372fe8fb19SBen Gras static char *sccsid = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
382fe8fb19SBen Gras static char *sccsid = "@(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC";
392fe8fb19SBen Gras #else
40*0a6a1f1dSLionel Sambuc __RCSID("$NetBSD: xdr_float.c,v 1.40 2014/08/24 17:07:00 matt Exp $");
412fe8fb19SBen Gras #endif
422fe8fb19SBen Gras #endif
432fe8fb19SBen Gras
442fe8fb19SBen Gras /*
452fe8fb19SBen Gras * xdr_float.c, Generic XDR routines implementation.
462fe8fb19SBen Gras *
472fe8fb19SBen Gras * Copyright (C) 1984, Sun Microsystems, Inc.
482fe8fb19SBen Gras *
492fe8fb19SBen Gras * These are the "floating point" xdr routines used to (de)serialize
502fe8fb19SBen Gras * most common data items. See xdr.h for more info on the interface to
512fe8fb19SBen Gras * xdr.
522fe8fb19SBen Gras */
532fe8fb19SBen Gras
542fe8fb19SBen Gras #include "namespace.h"
552fe8fb19SBen Gras
562fe8fb19SBen Gras #include <sys/types.h>
572fe8fb19SBen Gras #include <sys/param.h>
582fe8fb19SBen Gras
592fe8fb19SBen Gras #include <stdio.h>
602fe8fb19SBen Gras
612fe8fb19SBen Gras #include <rpc/types.h>
622fe8fb19SBen Gras #include <rpc/xdr.h>
632fe8fb19SBen Gras
642fe8fb19SBen Gras #ifdef __weak_alias
652fe8fb19SBen Gras __weak_alias(xdr_double,_xdr_double)
662fe8fb19SBen Gras __weak_alias(xdr_float,_xdr_float)
672fe8fb19SBen Gras #endif
682fe8fb19SBen Gras
692fe8fb19SBen Gras /*
702fe8fb19SBen Gras * NB: Not portable.
712fe8fb19SBen Gras * This routine works on machines with IEEE754 FP and Vaxen.
722fe8fb19SBen Gras */
732fe8fb19SBen Gras
74*0a6a1f1dSLionel Sambuc #if !defined(__vax__)
752fe8fb19SBen Gras #include <machine/endian.h>
762fe8fb19SBen Gras #define IEEEFP
772fe8fb19SBen Gras #endif
782fe8fb19SBen Gras
792fe8fb19SBen Gras #if defined(__vax__)
802fe8fb19SBen Gras
812fe8fb19SBen Gras /* What IEEE single precision floating point looks like on a Vax */
822fe8fb19SBen Gras struct ieee_single {
832fe8fb19SBen Gras unsigned int mantissa: 23;
842fe8fb19SBen Gras unsigned int exp : 8;
852fe8fb19SBen Gras unsigned int sign : 1;
862fe8fb19SBen Gras };
872fe8fb19SBen Gras
882fe8fb19SBen Gras /* Vax single precision floating point */
892fe8fb19SBen Gras struct vax_single {
902fe8fb19SBen Gras unsigned int mantissa1 : 7;
912fe8fb19SBen Gras unsigned int exp : 8;
922fe8fb19SBen Gras unsigned int sign : 1;
932fe8fb19SBen Gras unsigned int mantissa2 : 16;
942fe8fb19SBen Gras };
952fe8fb19SBen Gras
962fe8fb19SBen Gras #define VAX_SNG_BIAS 0x81
972fe8fb19SBen Gras #define IEEE_SNG_BIAS 0x7f
982fe8fb19SBen Gras
992fe8fb19SBen Gras static struct sgl_limits {
1002fe8fb19SBen Gras struct vax_single s;
1012fe8fb19SBen Gras struct ieee_single ieee;
1022fe8fb19SBen Gras } sgl_limits[2] = {
1032fe8fb19SBen Gras {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */
1042fe8fb19SBen Gras { 0x0, 0xff, 0x0 }}, /* Max IEEE */
1052fe8fb19SBen Gras {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */
1062fe8fb19SBen Gras { 0x0, 0x0, 0x0 }} /* Min IEEE */
1072fe8fb19SBen Gras };
1082fe8fb19SBen Gras #endif /* vax */
1092fe8fb19SBen Gras
1102fe8fb19SBen Gras bool_t
xdr_float(XDR * xdrs,float * fp)111f14fb602SLionel Sambuc xdr_float(XDR *xdrs, float *fp)
1122fe8fb19SBen Gras {
1132fe8fb19SBen Gras #ifndef IEEEFP
1142fe8fb19SBen Gras struct ieee_single is;
1152fe8fb19SBen Gras struct vax_single vs, *vsp;
1162fe8fb19SBen Gras struct sgl_limits *lim;
1172fe8fb19SBen Gras size_t i;
1182fe8fb19SBen Gras #endif
1192fe8fb19SBen Gras switch (xdrs->x_op) {
1202fe8fb19SBen Gras
1212fe8fb19SBen Gras case XDR_ENCODE:
1222fe8fb19SBen Gras #ifdef IEEEFP
1232fe8fb19SBen Gras return (XDR_PUTINT32(xdrs, (int32_t *)(void *)fp));
1242fe8fb19SBen Gras #else
125f14fb602SLionel Sambuc vs = *((struct vax_single *)(void *)fp);
1262fe8fb19SBen Gras for (i = 0, lim = sgl_limits;
1272fe8fb19SBen Gras i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
1282fe8fb19SBen Gras i++, lim++) {
1292fe8fb19SBen Gras if ((vs.mantissa2 == lim->s.mantissa2) &&
1302fe8fb19SBen Gras (vs.exp == lim->s.exp) &&
1312fe8fb19SBen Gras (vs.mantissa1 == lim->s.mantissa1)) {
1322fe8fb19SBen Gras is = lim->ieee;
1332fe8fb19SBen Gras goto shipit;
1342fe8fb19SBen Gras }
1352fe8fb19SBen Gras }
1362fe8fb19SBen Gras is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
1372fe8fb19SBen Gras is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
1382fe8fb19SBen Gras shipit:
1392fe8fb19SBen Gras is.sign = vs.sign;
1402fe8fb19SBen Gras return (XDR_PUTINT32(xdrs, (int32_t *)(void *)&is));
1412fe8fb19SBen Gras #endif
1422fe8fb19SBen Gras
1432fe8fb19SBen Gras case XDR_DECODE:
1442fe8fb19SBen Gras #ifdef IEEEFP
1452fe8fb19SBen Gras return (XDR_GETINT32(xdrs, (int32_t *)(void *)fp));
1462fe8fb19SBen Gras #else
147f14fb602SLionel Sambuc vsp = (struct vax_single *)(void *)fp;
1482fe8fb19SBen Gras if (!XDR_GETINT32(xdrs, (int32_t *)(void *)&is))
1492fe8fb19SBen Gras return (FALSE);
1502fe8fb19SBen Gras for (i = 0, lim = sgl_limits;
1512fe8fb19SBen Gras i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
1522fe8fb19SBen Gras i++, lim++) {
1532fe8fb19SBen Gras if ((is.exp == lim->ieee.exp) &&
1542fe8fb19SBen Gras (is.mantissa == lim->ieee.mantissa)) {
1552fe8fb19SBen Gras *vsp = lim->s;
1562fe8fb19SBen Gras goto doneit;
1572fe8fb19SBen Gras }
1582fe8fb19SBen Gras }
1592fe8fb19SBen Gras vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
1602fe8fb19SBen Gras vsp->mantissa2 = is.mantissa;
161f14fb602SLionel Sambuc vsp->mantissa1 = ((unsigned int)is.mantissa >> 16);
1622fe8fb19SBen Gras doneit:
1632fe8fb19SBen Gras vsp->sign = is.sign;
1642fe8fb19SBen Gras return (TRUE);
1652fe8fb19SBen Gras #endif
1662fe8fb19SBen Gras
1672fe8fb19SBen Gras case XDR_FREE:
1682fe8fb19SBen Gras return (TRUE);
1692fe8fb19SBen Gras }
1702fe8fb19SBen Gras /* NOTREACHED */
1712fe8fb19SBen Gras return (FALSE);
1722fe8fb19SBen Gras }
1732fe8fb19SBen Gras
1742fe8fb19SBen Gras #if defined(__vax__)
1752fe8fb19SBen Gras /* What IEEE double precision floating point looks like on a Vax */
1762fe8fb19SBen Gras struct ieee_double {
1772fe8fb19SBen Gras unsigned int mantissa1 : 20;
1782fe8fb19SBen Gras unsigned int exp : 11;
1792fe8fb19SBen Gras unsigned int sign : 1;
1802fe8fb19SBen Gras unsigned int mantissa2 : 32;
1812fe8fb19SBen Gras };
1822fe8fb19SBen Gras
1832fe8fb19SBen Gras /* Vax double precision floating point */
1842fe8fb19SBen Gras struct vax_double {
1852fe8fb19SBen Gras unsigned int mantissa1 : 7;
1862fe8fb19SBen Gras unsigned int exp : 8;
1872fe8fb19SBen Gras unsigned int sign : 1;
1882fe8fb19SBen Gras unsigned int mantissa2 : 16;
1892fe8fb19SBen Gras unsigned int mantissa3 : 16;
1902fe8fb19SBen Gras unsigned int mantissa4 : 16;
1912fe8fb19SBen Gras };
1922fe8fb19SBen Gras
1932fe8fb19SBen Gras #define VAX_DBL_BIAS 0x81
1942fe8fb19SBen Gras #define IEEE_DBL_BIAS 0x3ff
1952fe8fb19SBen Gras #define MASK(nbits) ((1 << nbits) - 1)
1962fe8fb19SBen Gras
1972fe8fb19SBen Gras static struct dbl_limits {
1982fe8fb19SBen Gras struct vax_double d;
1992fe8fb19SBen Gras struct ieee_double ieee;
2002fe8fb19SBen Gras } dbl_limits[2] = {
2012fe8fb19SBen Gras {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */
2022fe8fb19SBen Gras { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */
2032fe8fb19SBen Gras {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */
2042fe8fb19SBen Gras { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */
2052fe8fb19SBen Gras };
2062fe8fb19SBen Gras
2072fe8fb19SBen Gras #endif /* vax */
2082fe8fb19SBen Gras
2092fe8fb19SBen Gras
2102fe8fb19SBen Gras bool_t
xdr_double(XDR * xdrs,double * dp)211f14fb602SLionel Sambuc xdr_double(XDR *xdrs, double *dp)
2122fe8fb19SBen Gras {
2132fe8fb19SBen Gras #ifdef IEEEFP
2142fe8fb19SBen Gras int32_t *i32p;
2152fe8fb19SBen Gras bool_t rv;
2162fe8fb19SBen Gras #else
2172fe8fb19SBen Gras int32_t *lp;
2182fe8fb19SBen Gras struct ieee_double id;
2192fe8fb19SBen Gras struct vax_double vd;
2202fe8fb19SBen Gras struct dbl_limits *lim;
2212fe8fb19SBen Gras size_t i;
2222fe8fb19SBen Gras #endif
2232fe8fb19SBen Gras
2242fe8fb19SBen Gras switch (xdrs->x_op) {
2252fe8fb19SBen Gras
2262fe8fb19SBen Gras case XDR_ENCODE:
2272fe8fb19SBen Gras #ifdef IEEEFP
2282fe8fb19SBen Gras i32p = (int32_t *)(void *)dp;
2292fe8fb19SBen Gras #if (BYTE_ORDER == BIG_ENDIAN) || \
2302fe8fb19SBen Gras (defined(__arm__) && !defined(__VFP_FP__))
2312fe8fb19SBen Gras rv = XDR_PUTINT32(xdrs, i32p);
2322fe8fb19SBen Gras if (!rv)
2332fe8fb19SBen Gras return (rv);
2342fe8fb19SBen Gras rv = XDR_PUTINT32(xdrs, i32p+1);
2352fe8fb19SBen Gras #else
2362fe8fb19SBen Gras rv = XDR_PUTINT32(xdrs, i32p+1);
2372fe8fb19SBen Gras if (!rv)
2382fe8fb19SBen Gras return (rv);
2392fe8fb19SBen Gras rv = XDR_PUTINT32(xdrs, i32p);
2402fe8fb19SBen Gras #endif
2412fe8fb19SBen Gras return (rv);
2422fe8fb19SBen Gras #else
243f14fb602SLionel Sambuc vd = *((struct vax_double *)(void *)dp);
2442fe8fb19SBen Gras for (i = 0, lim = dbl_limits;
2452fe8fb19SBen Gras i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
2462fe8fb19SBen Gras i++, lim++) {
2472fe8fb19SBen Gras if ((vd.mantissa4 == lim->d.mantissa4) &&
2482fe8fb19SBen Gras (vd.mantissa3 == lim->d.mantissa3) &&
2492fe8fb19SBen Gras (vd.mantissa2 == lim->d.mantissa2) &&
2502fe8fb19SBen Gras (vd.mantissa1 == lim->d.mantissa1) &&
2512fe8fb19SBen Gras (vd.exp == lim->d.exp)) {
2522fe8fb19SBen Gras id = lim->ieee;
2532fe8fb19SBen Gras goto shipit;
2542fe8fb19SBen Gras }
2552fe8fb19SBen Gras }
2562fe8fb19SBen Gras id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
257f14fb602SLionel Sambuc id.mantissa1 = (vd.mantissa1 << 13) |
258f14fb602SLionel Sambuc ((unsigned int)vd.mantissa2 >> 3);
2592fe8fb19SBen Gras id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
2602fe8fb19SBen Gras (vd.mantissa3 << 13) |
261f14fb602SLionel Sambuc (((unsigned int)vd.mantissa4 >> 3) & MASK(13));
2622fe8fb19SBen Gras shipit:
2632fe8fb19SBen Gras id.sign = vd.sign;
2642fe8fb19SBen Gras lp = (int32_t *)(void *)&id;
2652fe8fb19SBen Gras return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp));
2662fe8fb19SBen Gras #endif
2672fe8fb19SBen Gras
2682fe8fb19SBen Gras case XDR_DECODE:
2692fe8fb19SBen Gras #ifdef IEEEFP
2702fe8fb19SBen Gras i32p = (int32_t *)(void *)dp;
2712fe8fb19SBen Gras #if BYTE_ORDER == BIG_ENDIAN || \
2722fe8fb19SBen Gras (defined(__arm__) && !defined(__VFP_FP__))
2732fe8fb19SBen Gras rv = XDR_GETINT32(xdrs, i32p);
2742fe8fb19SBen Gras if (!rv)
2752fe8fb19SBen Gras return (rv);
2762fe8fb19SBen Gras rv = XDR_GETINT32(xdrs, i32p+1);
2772fe8fb19SBen Gras #else
2782fe8fb19SBen Gras rv = XDR_GETINT32(xdrs, i32p+1);
2792fe8fb19SBen Gras if (!rv)
2802fe8fb19SBen Gras return (rv);
2812fe8fb19SBen Gras rv = XDR_GETINT32(xdrs, i32p);
2822fe8fb19SBen Gras #endif
2832fe8fb19SBen Gras return (rv);
2842fe8fb19SBen Gras #else
2852fe8fb19SBen Gras lp = (int32_t *)(void *)&id;
2862fe8fb19SBen Gras if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp))
2872fe8fb19SBen Gras return (FALSE);
2882fe8fb19SBen Gras for (i = 0, lim = dbl_limits;
2892fe8fb19SBen Gras i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
2902fe8fb19SBen Gras i++, lim++) {
2912fe8fb19SBen Gras if ((id.mantissa2 == lim->ieee.mantissa2) &&
2922fe8fb19SBen Gras (id.mantissa1 == lim->ieee.mantissa1) &&
2932fe8fb19SBen Gras (id.exp == lim->ieee.exp)) {
2942fe8fb19SBen Gras vd = lim->d;
2952fe8fb19SBen Gras goto doneit;
2962fe8fb19SBen Gras }
2972fe8fb19SBen Gras }
2982fe8fb19SBen Gras vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
299f14fb602SLionel Sambuc vd.mantissa1 = ((unsigned int)id.mantissa1 >> 13);
3002fe8fb19SBen Gras vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
301f14fb602SLionel Sambuc ((unsigned int)id.mantissa2 >> 29);
302f14fb602SLionel Sambuc vd.mantissa3 = ((unsigned int)id.mantissa2 >> 13);
3032fe8fb19SBen Gras vd.mantissa4 = (id.mantissa2 << 3);
3042fe8fb19SBen Gras doneit:
3052fe8fb19SBen Gras vd.sign = id.sign;
3062fe8fb19SBen Gras *dp = *((double *)(void *)&vd);
3072fe8fb19SBen Gras return (TRUE);
3082fe8fb19SBen Gras #endif
3092fe8fb19SBen Gras
3102fe8fb19SBen Gras case XDR_FREE:
3112fe8fb19SBen Gras return (TRUE);
3122fe8fb19SBen Gras }
3132fe8fb19SBen Gras /* NOTREACHED */
3142fe8fb19SBen Gras return (FALSE);
3152fe8fb19SBen Gras }
316