1 /* $NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt 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 #if defined(LIBC_SCCS) && !defined(lint) 35 static char *sccsid2 = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro"; 36 static char *sccsid = "@(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC"; 37 #endif 38 #include <sys/cdefs.h> 39 __FBSDID("$FreeBSD$"); 40 41 /* 42 * xdr_float.c, Generic XDR routines implementation. 43 * 44 * These are the "floating point" xdr routines used to (de)serialize 45 * most common data items. See xdr.h for more info on the interface to 46 * xdr. 47 */ 48 49 #include "namespace.h" 50 #include <sys/types.h> 51 #include <sys/param.h> 52 53 #include <stdio.h> 54 55 #include <rpc/types.h> 56 #include <rpc/xdr.h> 57 #include "un-namespace.h" 58 59 /* 60 * NB: Not portable. 61 * This routine works on machines with IEEE754 FP and Vaxen. 62 */ 63 64 #if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \ 65 defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \ 66 defined(__arm__) || defined(__ppc__) || \ 67 defined(__arm26__) || defined(__sparc64__) || defined(__amd64__) || \ 68 defined(__aarch64__) 69 #include <machine/endian.h> 70 #define IEEEFP 71 #endif 72 73 #if defined(__vax__) 74 75 /* What IEEE single precision floating point looks like on a Vax */ 76 struct ieee_single { 77 unsigned int mantissa: 23; 78 unsigned int exp : 8; 79 unsigned int sign : 1; 80 }; 81 82 /* Vax single precision floating point */ 83 struct vax_single { 84 unsigned int mantissa1 : 7; 85 unsigned int exp : 8; 86 unsigned int sign : 1; 87 unsigned int mantissa2 : 16; 88 }; 89 90 #define VAX_SNG_BIAS 0x81 91 #define IEEE_SNG_BIAS 0x7f 92 93 static struct sgl_limits { 94 struct vax_single s; 95 struct ieee_single ieee; 96 } sgl_limits[2] = { 97 {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ 98 { 0x0, 0xff, 0x0 }}, /* Max IEEE */ 99 {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ 100 { 0x0, 0x0, 0x0 }} /* Min IEEE */ 101 }; 102 #endif /* vax */ 103 104 bool_t 105 xdr_float(xdrs, fp) 106 XDR *xdrs; 107 float *fp; 108 { 109 #ifndef IEEEFP 110 struct ieee_single is; 111 struct vax_single vs, *vsp; 112 struct sgl_limits *lim; 113 int i; 114 #endif 115 switch (xdrs->x_op) { 116 117 case XDR_ENCODE: 118 #ifdef IEEEFP 119 return (XDR_PUTINT32(xdrs, (int32_t *)fp)); 120 #else 121 vs = *((struct vax_single *)fp); 122 for (i = 0, lim = sgl_limits; 123 i < sizeof(sgl_limits)/sizeof(struct sgl_limits); 124 i++, lim++) { 125 if ((vs.mantissa2 == lim->s.mantissa2) && 126 (vs.exp == lim->s.exp) && 127 (vs.mantissa1 == lim->s.mantissa1)) { 128 is = lim->ieee; 129 goto shipit; 130 } 131 } 132 is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; 133 is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; 134 shipit: 135 is.sign = vs.sign; 136 return (XDR_PUTINT32(xdrs, (int32_t *)&is)); 137 #endif 138 139 case XDR_DECODE: 140 #ifdef IEEEFP 141 return (XDR_GETINT32(xdrs, (int32_t *)fp)); 142 #else 143 vsp = (struct vax_single *)fp; 144 if (!XDR_GETINT32(xdrs, (int32_t *)&is)) 145 return (FALSE); 146 for (i = 0, lim = sgl_limits; 147 i < sizeof(sgl_limits)/sizeof(struct sgl_limits); 148 i++, lim++) { 149 if ((is.exp == lim->ieee.exp) && 150 (is.mantissa == lim->ieee.mantissa)) { 151 *vsp = lim->s; 152 goto doneit; 153 } 154 } 155 vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; 156 vsp->mantissa2 = is.mantissa; 157 vsp->mantissa1 = (is.mantissa >> 16); 158 doneit: 159 vsp->sign = is.sign; 160 return (TRUE); 161 #endif 162 163 case XDR_FREE: 164 return (TRUE); 165 } 166 /* NOTREACHED */ 167 return (FALSE); 168 } 169 170 #if defined(__vax__) 171 /* What IEEE double precision floating point looks like on a Vax */ 172 struct ieee_double { 173 unsigned int mantissa1 : 20; 174 unsigned int exp : 11; 175 unsigned int sign : 1; 176 unsigned int mantissa2 : 32; 177 }; 178 179 /* Vax double precision floating point */ 180 struct vax_double { 181 unsigned int mantissa1 : 7; 182 unsigned int exp : 8; 183 unsigned int sign : 1; 184 unsigned int mantissa2 : 16; 185 unsigned int mantissa3 : 16; 186 unsigned int mantissa4 : 16; 187 }; 188 189 #define VAX_DBL_BIAS 0x81 190 #define IEEE_DBL_BIAS 0x3ff 191 #define MASK(nbits) ((1 << nbits) - 1) 192 193 static struct dbl_limits { 194 struct vax_double d; 195 struct ieee_double ieee; 196 } dbl_limits[2] = { 197 {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ 198 { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ 199 {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ 200 { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ 201 }; 202 203 #endif /* vax */ 204 205 206 bool_t 207 xdr_double(XDR *xdrs, double *dp) 208 { 209 #ifdef IEEEFP 210 int32_t *i32p; 211 bool_t rv; 212 #else 213 int32_t *lp; 214 struct ieee_double id; 215 struct vax_double vd; 216 struct dbl_limits *lim; 217 int i; 218 #endif 219 220 switch (xdrs->x_op) { 221 222 case XDR_ENCODE: 223 #ifdef IEEEFP 224 i32p = (int32_t *)(void *)dp; 225 #if BYTE_ORDER == BIG_ENDIAN 226 rv = XDR_PUTINT32(xdrs, i32p); 227 if (!rv) 228 return (rv); 229 rv = XDR_PUTINT32(xdrs, i32p+1); 230 #else 231 rv = XDR_PUTINT32(xdrs, i32p+1); 232 if (!rv) 233 return (rv); 234 rv = XDR_PUTINT32(xdrs, i32p); 235 #endif 236 return (rv); 237 #else 238 vd = *((struct vax_double *)dp); 239 for (i = 0, lim = dbl_limits; 240 i < sizeof(dbl_limits)/sizeof(struct dbl_limits); 241 i++, lim++) { 242 if ((vd.mantissa4 == lim->d.mantissa4) && 243 (vd.mantissa3 == lim->d.mantissa3) && 244 (vd.mantissa2 == lim->d.mantissa2) && 245 (vd.mantissa1 == lim->d.mantissa1) && 246 (vd.exp == lim->d.exp)) { 247 id = lim->ieee; 248 goto shipit; 249 } 250 } 251 id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; 252 id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); 253 id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | 254 (vd.mantissa3 << 13) | 255 ((vd.mantissa4 >> 3) & MASK(13)); 256 shipit: 257 id.sign = vd.sign; 258 lp = (int32_t *)&id; 259 return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp)); 260 #endif 261 262 case XDR_DECODE: 263 #ifdef IEEEFP 264 i32p = (int32_t *)(void *)dp; 265 #if BYTE_ORDER == BIG_ENDIAN 266 rv = XDR_GETINT32(xdrs, i32p); 267 if (!rv) 268 return (rv); 269 rv = XDR_GETINT32(xdrs, i32p+1); 270 #else 271 rv = XDR_GETINT32(xdrs, i32p+1); 272 if (!rv) 273 return (rv); 274 rv = XDR_GETINT32(xdrs, i32p); 275 #endif 276 return (rv); 277 #else 278 lp = (int32_t *)&id; 279 if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp)) 280 return (FALSE); 281 for (i = 0, lim = dbl_limits; 282 i < sizeof(dbl_limits)/sizeof(struct dbl_limits); 283 i++, lim++) { 284 if ((id.mantissa2 == lim->ieee.mantissa2) && 285 (id.mantissa1 == lim->ieee.mantissa1) && 286 (id.exp == lim->ieee.exp)) { 287 vd = lim->d; 288 goto doneit; 289 } 290 } 291 vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; 292 vd.mantissa1 = (id.mantissa1 >> 13); 293 vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | 294 (id.mantissa2 >> 29); 295 vd.mantissa3 = (id.mantissa2 >> 13); 296 vd.mantissa4 = (id.mantissa2 << 3); 297 doneit: 298 vd.sign = id.sign; 299 *dp = *((double *)&vd); 300 return (TRUE); 301 #endif 302 303 case XDR_FREE: 304 return (TRUE); 305 } 306 /* NOTREACHED */ 307 return (FALSE); 308 } 309