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