1 /* $NetBSD: xdr_float.c,v 1.41 2016/02/15 11:07:48 martin Exp $ */ 2 3 /* 4 * Copyright (c) 2010, Oracle America, Inc. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following 14 * disclaimer in the documentation and/or other materials 15 * provided with the distribution. 16 * * Neither the name of the "Oracle America, Inc." nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 #if defined(LIBC_SCCS) && !defined(lint) 36 #if 0 37 static char *sccsid = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro"; 38 static char *sccsid = "@(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC"; 39 #else 40 __RCSID("$NetBSD: xdr_float.c,v 1.41 2016/02/15 11:07:48 martin Exp $"); 41 #endif 42 #endif 43 44 /* 45 * xdr_float.c, Generic XDR routines implementation. 46 * 47 * Copyright (C) 1984, Sun Microsystems, Inc. 48 * 49 * These are the "floating point" xdr routines used to (de)serialize 50 * most common data items. See xdr.h for more info on the interface to 51 * xdr. 52 */ 53 54 #include "namespace.h" 55 56 #include <sys/types.h> 57 #include <sys/param.h> 58 59 #include <stdio.h> 60 #include <string.h> 61 62 #include <rpc/types.h> 63 #include <rpc/xdr.h> 64 65 #ifdef __weak_alias 66 __weak_alias(xdr_double,_xdr_double) 67 __weak_alias(xdr_float,_xdr_float) 68 #endif 69 70 /* 71 * NB: Not portable. 72 * This routine works on machines with IEEE754 FP and Vaxen. 73 */ 74 75 #if !defined(__vax__) 76 #include <machine/endian.h> 77 #define IEEEFP 78 #endif 79 80 #if defined(__vax__) 81 82 /* What IEEE single precision floating point looks like on a Vax */ 83 struct ieee_single { 84 unsigned int mantissa: 23; 85 unsigned int exp : 8; 86 unsigned int sign : 1; 87 }; 88 89 /* Vax single precision floating point */ 90 struct vax_single { 91 unsigned int mantissa1 : 7; 92 unsigned int exp : 8; 93 unsigned int sign : 1; 94 unsigned int mantissa2 : 16; 95 }; 96 97 #define VAX_SNG_BIAS 0x81 98 #define IEEE_SNG_BIAS 0x7f 99 100 static struct sgl_limits { 101 struct vax_single s; 102 struct ieee_single ieee; 103 } sgl_limits[2] = { 104 {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ 105 { 0x0, 0xff, 0x0 }}, /* Max IEEE */ 106 {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ 107 { 0x0, 0x0, 0x0 }} /* Min IEEE */ 108 }; 109 #endif /* vax */ 110 111 bool_t 112 xdr_float(XDR *xdrs, float *fp) 113 { 114 #ifndef IEEEFP 115 struct ieee_single is; 116 struct vax_single vs, *vsp; 117 struct sgl_limits *lim; 118 size_t i; 119 #endif 120 switch (xdrs->x_op) { 121 122 case XDR_ENCODE: 123 #ifdef IEEEFP 124 return (XDR_PUTINT32(xdrs, (int32_t *)(void *)fp)); 125 #else 126 vs = *((struct vax_single *)(void *)fp); 127 for (i = 0, lim = sgl_limits; 128 i < sizeof(sgl_limits)/sizeof(struct sgl_limits); 129 i++, lim++) { 130 if ((vs.mantissa2 == lim->s.mantissa2) && 131 (vs.exp == lim->s.exp) && 132 (vs.mantissa1 == lim->s.mantissa1)) { 133 is = lim->ieee; 134 goto shipit; 135 } 136 } 137 is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; 138 is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; 139 shipit: 140 is.sign = vs.sign; 141 return (XDR_PUTINT32(xdrs, (int32_t *)(void *)&is)); 142 #endif 143 144 case XDR_DECODE: 145 #ifdef IEEEFP 146 return (XDR_GETINT32(xdrs, (int32_t *)(void *)fp)); 147 #else 148 vsp = (struct vax_single *)(void *)fp; 149 if (!XDR_GETINT32(xdrs, (int32_t *)(void *)&is)) 150 return (FALSE); 151 for (i = 0, lim = sgl_limits; 152 i < sizeof(sgl_limits)/sizeof(struct sgl_limits); 153 i++, lim++) { 154 if ((is.exp == lim->ieee.exp) && 155 (is.mantissa == lim->ieee.mantissa)) { 156 *vsp = lim->s; 157 goto doneit; 158 } 159 } 160 vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; 161 vsp->mantissa2 = is.mantissa; 162 vsp->mantissa1 = ((unsigned int)is.mantissa >> 16); 163 doneit: 164 vsp->sign = is.sign; 165 return (TRUE); 166 #endif 167 168 case XDR_FREE: 169 return (TRUE); 170 } 171 /* NOTREACHED */ 172 return (FALSE); 173 } 174 175 #if defined(__vax__) 176 /* What IEEE double precision floating point looks like on a Vax */ 177 struct ieee_double { 178 unsigned int mantissa1 : 20; 179 unsigned int exp : 11; 180 unsigned int sign : 1; 181 unsigned int mantissa2 : 32; 182 }; 183 184 /* Vax double precision floating point */ 185 struct vax_double { 186 unsigned int mantissa1 : 7; 187 unsigned int exp : 8; 188 unsigned int sign : 1; 189 unsigned int mantissa2 : 16; 190 unsigned int mantissa3 : 16; 191 unsigned int mantissa4 : 16; 192 }; 193 194 #define VAX_DBL_BIAS 0x81 195 #define IEEE_DBL_BIAS 0x3ff 196 #define MASK(nbits) ((1 << nbits) - 1) 197 198 static struct dbl_limits { 199 struct vax_double d; 200 struct ieee_double ieee; 201 } dbl_limits[2] = { 202 {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ 203 { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ 204 {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ 205 { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ 206 }; 207 208 #endif /* vax */ 209 210 211 bool_t 212 xdr_double(XDR *xdrs, double *dp) 213 { 214 #ifdef IEEEFP 215 int32_t *i32p; 216 bool_t rv; 217 #else 218 int32_t *lp; 219 struct ieee_double id; 220 struct vax_double vd; 221 struct dbl_limits *lim; 222 size_t i; 223 #endif 224 225 switch (xdrs->x_op) { 226 227 case XDR_ENCODE: 228 #ifdef IEEEFP 229 i32p = (int32_t *)(void *)dp; 230 #if (BYTE_ORDER == BIG_ENDIAN) || \ 231 (defined(__arm__) && !defined(__VFP_FP__)) 232 rv = XDR_PUTINT32(xdrs, i32p); 233 if (!rv) 234 return (rv); 235 rv = XDR_PUTINT32(xdrs, i32p+1); 236 #else 237 rv = XDR_PUTINT32(xdrs, i32p+1); 238 if (!rv) 239 return (rv); 240 rv = XDR_PUTINT32(xdrs, i32p); 241 #endif 242 return (rv); 243 #else 244 vd = *((struct vax_double *)(void *)dp); 245 for (i = 0, lim = dbl_limits; 246 i < sizeof(dbl_limits)/sizeof(struct dbl_limits); 247 i++, lim++) { 248 if ((vd.mantissa4 == lim->d.mantissa4) && 249 (vd.mantissa3 == lim->d.mantissa3) && 250 (vd.mantissa2 == lim->d.mantissa2) && 251 (vd.mantissa1 == lim->d.mantissa1) && 252 (vd.exp == lim->d.exp)) { 253 id = lim->ieee; 254 goto shipit; 255 } 256 } 257 id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; 258 id.mantissa1 = (vd.mantissa1 << 13) | 259 ((unsigned int)vd.mantissa2 >> 3); 260 id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | 261 (vd.mantissa3 << 13) | 262 (((unsigned int)vd.mantissa4 >> 3) & MASK(13)); 263 shipit: 264 id.sign = vd.sign; 265 lp = (int32_t *)(void *)&id; 266 return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp)); 267 #endif 268 269 case XDR_DECODE: 270 #ifdef IEEEFP 271 i32p = (int32_t *)(void *)dp; 272 #if BYTE_ORDER == BIG_ENDIAN || \ 273 (defined(__arm__) && !defined(__VFP_FP__)) 274 rv = XDR_GETINT32(xdrs, i32p); 275 if (!rv) 276 return (rv); 277 rv = XDR_GETINT32(xdrs, i32p+1); 278 #else 279 rv = XDR_GETINT32(xdrs, i32p+1); 280 if (!rv) 281 return (rv); 282 rv = XDR_GETINT32(xdrs, i32p); 283 #endif 284 return (rv); 285 #else 286 lp = (int32_t *)(void *)&id; 287 if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp)) 288 return (FALSE); 289 for (i = 0, lim = dbl_limits; 290 i < sizeof(dbl_limits)/sizeof(struct dbl_limits); 291 i++, lim++) { 292 if ((id.mantissa2 == lim->ieee.mantissa2) && 293 (id.mantissa1 == lim->ieee.mantissa1) && 294 (id.exp == lim->ieee.exp)) { 295 vd = lim->d; 296 goto doneit; 297 } 298 } 299 vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; 300 vd.mantissa1 = ((unsigned int)id.mantissa1 >> 13); 301 vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | 302 ((unsigned int)id.mantissa2 >> 29); 303 vd.mantissa3 = ((unsigned int)id.mantissa2 >> 13); 304 vd.mantissa4 = (id.mantissa2 << 3); 305 doneit: 306 vd.sign = id.sign; 307 memcpy(dp, &vd, sizeof(double)); 308 return (TRUE); 309 #endif 310 311 case XDR_FREE: 312 return (TRUE); 313 } 314 /* NOTREACHED */ 315 return (FALSE); 316 } 317