1 /* 2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 3 * unrestricted use provided that this legend is included on all tape 4 * media and as a part of the software program in whole or part. Users 5 * may copy or modify Sun RPC without charge, but are not authorized 6 * to license or distribute it to anyone else except as part of a product or 7 * program developed by the user. 8 * 9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 12 * 13 * Sun RPC is provided with no support and without any obligation on the 14 * part of Sun Microsystems, Inc. to assist in its use, correction, 15 * modification or enhancement. 16 * 17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 19 * OR ANY PART THEREOF. 20 * 21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 22 * or profits or other special, indirect and consequential damages, even if 23 * Sun has been advised of the possibility of such damages. 24 * 25 * Sun Microsystems, Inc. 26 * 2550 Garcia Avenue 27 * Mountain View, California 94043 28 * 29 * @(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro 30 * @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC 31 * $NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt Exp $ 32 * $FreeBSD: src/lib/libc/xdr/xdr_float.c,v 1.14 2004/10/16 06:32:43 obrien Exp $ 33 * $DragonFly: src/lib/libc/xdr/xdr_float.c,v 1.6 2006/07/27 00:43:17 corecode Exp $ 34 */ 35 36 /* 37 * xdr_float.c, Generic XDR routines implementation. 38 * 39 * Copyright (C) 1984, Sun Microsystems, Inc. 40 * 41 * These are the "floating point" xdr routines used to (de)serialize 42 * most common data items. See xdr.h for more info on the interface to 43 * xdr. 44 */ 45 46 #include "namespace.h" 47 #include <sys/types.h> 48 #include <sys/param.h> 49 50 #include <stdio.h> 51 52 #include <rpc/types.h> 53 #include <rpc/xdr.h> 54 #include "un-namespace.h" 55 56 /* 57 * NB: Not portable. 58 * This routine works on machines with IEEE754 FP and Vaxen. 59 */ 60 61 #if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \ 62 defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \ 63 defined(__arm__) || defined(__ppc__) || defined(__ia64__) || \ 64 defined(__arm26__) || defined(__sparc64__) || defined(__x86_64__) 65 #include <machine/endian.h> 66 #define IEEEFP 67 #endif 68 69 #if defined(__vax__) 70 71 /* What IEEE single precision floating point looks like on a Vax */ 72 struct ieee_single { 73 unsigned int mantissa: 23; 74 unsigned int exp : 8; 75 unsigned int sign : 1; 76 }; 77 78 /* Vax single precision floating point */ 79 struct vax_single { 80 unsigned int mantissa1 : 7; 81 unsigned int exp : 8; 82 unsigned int sign : 1; 83 unsigned int mantissa2 : 16; 84 }; 85 86 #define VAX_SNG_BIAS 0x81 87 #define IEEE_SNG_BIAS 0x7f 88 89 static struct sgl_limits { 90 struct vax_single s; 91 struct ieee_single ieee; 92 } sgl_limits[2] = { 93 {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ 94 { 0x0, 0xff, 0x0 }}, /* Max IEEE */ 95 {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ 96 { 0x0, 0x0, 0x0 }} /* Min IEEE */ 97 }; 98 #endif /* vax */ 99 100 bool_t 101 xdr_float(XDR *xdrs, float *fp) 102 { 103 #ifndef IEEEFP 104 struct ieee_single is; 105 struct vax_single vs, *vsp; 106 struct sgl_limits *lim; 107 int i; 108 #endif 109 switch (xdrs->x_op) { 110 111 case XDR_ENCODE: 112 #ifdef IEEEFP 113 return (XDR_PUTINT32(xdrs, (int32_t *)fp)); 114 #else 115 vs = *((struct vax_single *)fp); 116 for (i = 0, lim = sgl_limits; 117 i < sizeof(sgl_limits)/sizeof(struct sgl_limits); 118 i++, lim++) { 119 if ((vs.mantissa2 == lim->s.mantissa2) && 120 (vs.exp == lim->s.exp) && 121 (vs.mantissa1 == lim->s.mantissa1)) { 122 is = lim->ieee; 123 goto shipit; 124 } 125 } 126 is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; 127 is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; 128 shipit: 129 is.sign = vs.sign; 130 return (XDR_PUTINT32(xdrs, (int32_t *)&is)); 131 #endif 132 133 case XDR_DECODE: 134 #ifdef IEEEFP 135 return (XDR_GETINT32(xdrs, (int32_t *)fp)); 136 #else 137 vsp = (struct vax_single *)fp; 138 if (!XDR_GETINT32(xdrs, (int32_t *)&is)) 139 return (FALSE); 140 for (i = 0, lim = sgl_limits; 141 i < sizeof(sgl_limits)/sizeof(struct sgl_limits); 142 i++, lim++) { 143 if ((is.exp == lim->ieee.exp) && 144 (is.mantissa == lim->ieee.mantissa)) { 145 *vsp = lim->s; 146 goto doneit; 147 } 148 } 149 vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; 150 vsp->mantissa2 = is.mantissa; 151 vsp->mantissa1 = (is.mantissa >> 16); 152 doneit: 153 vsp->sign = is.sign; 154 return (TRUE); 155 #endif 156 157 case XDR_FREE: 158 return (TRUE); 159 } 160 /* NOTREACHED */ 161 return (FALSE); 162 } 163 164 #if defined(__vax__) 165 /* What IEEE double precision floating point looks like on a Vax */ 166 struct ieee_double { 167 unsigned int mantissa1 : 20; 168 unsigned int exp : 11; 169 unsigned int sign : 1; 170 unsigned int mantissa2 : 32; 171 }; 172 173 /* Vax double precision floating point */ 174 struct vax_double { 175 unsigned int mantissa1 : 7; 176 unsigned int exp : 8; 177 unsigned int sign : 1; 178 unsigned int mantissa2 : 16; 179 unsigned int mantissa3 : 16; 180 unsigned int mantissa4 : 16; 181 }; 182 183 #define VAX_DBL_BIAS 0x81 184 #define IEEE_DBL_BIAS 0x3ff 185 #define MASK(nbits) ((1 << nbits) - 1) 186 187 static struct dbl_limits { 188 struct vax_double d; 189 struct ieee_double ieee; 190 } dbl_limits[2] = { 191 {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ 192 { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ 193 {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ 194 { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ 195 }; 196 197 #endif /* vax */ 198 199 200 bool_t 201 xdr_double(XDR *xdrs, double *dp) 202 { 203 #ifdef IEEEFP 204 int32_t *i32p; 205 bool_t rv; 206 #else 207 int32_t *lp; 208 struct ieee_double id; 209 struct vax_double vd; 210 struct dbl_limits *lim; 211 int i; 212 #endif 213 214 switch (xdrs->x_op) { 215 216 case XDR_ENCODE: 217 #ifdef IEEEFP 218 i32p = (int32_t *)(void *)dp; 219 #if BYTE_ORDER == BIG_ENDIAN 220 rv = XDR_PUTINT32(xdrs, i32p); 221 if (!rv) 222 return (rv); 223 rv = XDR_PUTINT32(xdrs, i32p+1); 224 #else 225 rv = XDR_PUTINT32(xdrs, i32p+1); 226 if (!rv) 227 return (rv); 228 rv = XDR_PUTINT32(xdrs, i32p); 229 #endif 230 return (rv); 231 #else 232 vd = *((struct vax_double *)dp); 233 for (i = 0, lim = dbl_limits; 234 i < sizeof(dbl_limits)/sizeof(struct dbl_limits); 235 i++, lim++) { 236 if ((vd.mantissa4 == lim->d.mantissa4) && 237 (vd.mantissa3 == lim->d.mantissa3) && 238 (vd.mantissa2 == lim->d.mantissa2) && 239 (vd.mantissa1 == lim->d.mantissa1) && 240 (vd.exp == lim->d.exp)) { 241 id = lim->ieee; 242 goto shipit; 243 } 244 } 245 id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; 246 id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); 247 id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | 248 (vd.mantissa3 << 13) | 249 ((vd.mantissa4 >> 3) & MASK(13)); 250 shipit: 251 id.sign = vd.sign; 252 lp = (int32_t *)&id; 253 return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp)); 254 #endif 255 256 case XDR_DECODE: 257 #ifdef IEEEFP 258 i32p = (int32_t *)(void *)dp; 259 #if BYTE_ORDER == BIG_ENDIAN 260 rv = XDR_GETINT32(xdrs, i32p); 261 if (!rv) 262 return (rv); 263 rv = XDR_GETINT32(xdrs, i32p+1); 264 #else 265 rv = XDR_GETINT32(xdrs, i32p+1); 266 if (!rv) 267 return (rv); 268 rv = XDR_GETINT32(xdrs, i32p); 269 #endif 270 return (rv); 271 #else 272 lp = (int32_t *)&id; 273 if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp)) 274 return (FALSE); 275 for (i = 0, lim = dbl_limits; 276 i < sizeof(dbl_limits)/sizeof(struct dbl_limits); 277 i++, lim++) { 278 if ((id.mantissa2 == lim->ieee.mantissa2) && 279 (id.mantissa1 == lim->ieee.mantissa1) && 280 (id.exp == lim->ieee.exp)) { 281 vd = lim->d; 282 goto doneit; 283 } 284 } 285 vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; 286 vd.mantissa1 = (id.mantissa1 >> 13); 287 vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | 288 (id.mantissa2 >> 29); 289 vd.mantissa3 = (id.mantissa2 >> 13); 290 vd.mantissa4 = (id.mantissa2 << 3); 291 doneit: 292 vd.sign = id.sign; 293 *dp = *((double *)&vd); 294 return (TRUE); 295 #endif 296 297 case XDR_FREE: 298 return (TRUE); 299 } 300 /* NOTREACHED */ 301 return (FALSE); 302 } 303