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 30 #if defined(LIBC_SCCS) && !defined(lint) 31 /*static char *sccsid = "from: @(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";*/ 32 /*static char *sccsid = "from: @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC";*/ 33 static char *rcsid = "$Id: xdr_float.c,v 1.3 1994/12/04 01:13:39 cgd Exp $"; 34 #endif 35 36 /* 37 * xdr_float.c, Generic XDR routines impelmentation. 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 <stdio.h> 47 #include <sys/types.h> 48 #include <sys/param.h> 49 #include <rpc/types.h> 50 #include <rpc/xdr.h> 51 52 /* 53 * NB: Not portable. 54 * This routine works on Suns (Sky / 68000's), i386's, MIPS, NS32k and Vaxen, 55 * Sparcs, and Alphas 56 */ 57 58 #if defined(mc68000)||defined(sparc)||defined(i386)||defined(mips)||defined(ns32k)||defined(alpha) 59 #define IEEEFP 60 #endif 61 62 #ifdef vax 63 64 /* What IEEE single precision floating point looks like on a Vax */ 65 struct ieee_single { 66 unsigned int mantissa: 23; 67 unsigned int exp : 8; 68 unsigned int sign : 1; 69 }; 70 71 /* Vax single precision floating point */ 72 struct vax_single { 73 unsigned int mantissa1 : 7; 74 unsigned int exp : 8; 75 unsigned int sign : 1; 76 unsigned int mantissa2 : 16; 77 }; 78 79 #define VAX_SNG_BIAS 0x81 80 #define IEEE_SNG_BIAS 0x7f 81 82 static struct sgl_limits { 83 struct vax_single s; 84 struct ieee_single ieee; 85 } sgl_limits[2] = { 86 {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ 87 { 0x0, 0xff, 0x0 }}, /* Max IEEE */ 88 {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ 89 { 0x0, 0x0, 0x0 }} /* Min IEEE */ 90 }; 91 #endif /* vax */ 92 93 bool_t 94 xdr_float(xdrs, fp) 95 register XDR *xdrs; 96 register float *fp; 97 { 98 #ifndef IEEEFP 99 struct ieee_single is; 100 struct vax_single vs, *vsp; 101 struct sgl_limits *lim; 102 int i; 103 #endif 104 switch (xdrs->x_op) { 105 106 case XDR_ENCODE: 107 #ifdef IEEEFP 108 return (XDR_PUTLONG(xdrs, (long *)fp)); 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 return (XDR_GETLONG(xdrs, (long *)fp)); 131 #else 132 vsp = (struct vax_single *)fp; 133 if (!XDR_GETLONG(xdrs, (long *)&is)) 134 return (FALSE); 135 for (i = 0, lim = sgl_limits; 136 i < sizeof(sgl_limits)/sizeof(struct sgl_limits); 137 i++, lim++) { 138 if ((is.exp == lim->ieee.exp) && 139 (is.mantissa == lim->ieee.mantissa)) { 140 *vsp = lim->s; 141 goto doneit; 142 } 143 } 144 vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; 145 vsp->mantissa2 = is.mantissa; 146 vsp->mantissa1 = (is.mantissa >> 16); 147 doneit: 148 vsp->sign = is.sign; 149 return (TRUE); 150 #endif 151 152 case XDR_FREE: 153 return (TRUE); 154 } 155 return (FALSE); 156 } 157 158 /* 159 * This routine works on Suns (Sky / 68000's), i386's, MIPS and Vaxen. 160 */ 161 162 #ifdef vax 163 /* What IEEE double precision floating point looks like on a Vax */ 164 struct ieee_double { 165 unsigned int mantissa1 : 20; 166 unsigned int exp : 11; 167 unsigned int sign : 1; 168 unsigned int mantissa2 : 32; 169 }; 170 171 /* Vax double precision floating point */ 172 struct vax_double { 173 unsigned int mantissa1 : 7; 174 unsigned int exp : 8; 175 unsigned int sign : 1; 176 unsigned int mantissa2 : 16; 177 unsigned int mantissa3 : 16; 178 unsigned int mantissa4 : 16; 179 }; 180 181 #define VAX_DBL_BIAS 0x81 182 #define IEEE_DBL_BIAS 0x3ff 183 #define MASK(nbits) ((1 << nbits) - 1) 184 185 static struct dbl_limits { 186 struct vax_double d; 187 struct ieee_double ieee; 188 } dbl_limits[2] = { 189 {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ 190 { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ 191 {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ 192 { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ 193 }; 194 195 #endif /* vax */ 196 197 198 bool_t 199 xdr_double(xdrs, dp) 200 register XDR *xdrs; 201 double *dp; 202 { 203 register long *lp; 204 #ifndef IEEEFP 205 struct ieee_double id; 206 struct vax_double vd; 207 register struct dbl_limits *lim; 208 int i; 209 #endif 210 211 switch (xdrs->x_op) { 212 213 case XDR_ENCODE: 214 #ifdef IEEEFP 215 lp = (long *)dp; 216 #if BYTE_ORDER == BIG_ENDIAN 217 return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp)); 218 #else 219 return (XDR_PUTLONG(xdrs, lp+1) && XDR_PUTLONG(xdrs, lp)); 220 #endif 221 #else 222 vd = *((struct vax_double *)dp); 223 for (i = 0, lim = dbl_limits; 224 i < sizeof(dbl_limits)/sizeof(struct dbl_limits); 225 i++, lim++) { 226 if ((vd.mantissa4 == lim->d.mantissa4) && 227 (vd.mantissa3 == lim->d.mantissa3) && 228 (vd.mantissa2 == lim->d.mantissa2) && 229 (vd.mantissa1 == lim->d.mantissa1) && 230 (vd.exp == lim->d.exp)) { 231 id = lim->ieee; 232 goto shipit; 233 } 234 } 235 id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; 236 id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); 237 id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | 238 (vd.mantissa3 << 13) | 239 ((vd.mantissa4 >> 3) & MASK(13)); 240 shipit: 241 id.sign = vd.sign; 242 lp = (long *)&id; 243 return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp)); 244 #endif 245 246 case XDR_DECODE: 247 #ifdef IEEEFP 248 lp = (long *)dp; 249 #if BYTE_ORDER == BIG_ENDIAN 250 return (XDR_GETLONG(xdrs, lp++) && XDR_GETLONG(xdrs, lp)); 251 #else 252 return (XDR_GETLONG(xdrs, lp+1) && XDR_GETLONG(xdrs, lp)); 253 #endif 254 #else 255 lp = (long *)&id; 256 if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp)) 257 return (FALSE); 258 for (i = 0, lim = dbl_limits; 259 i < sizeof(dbl_limits)/sizeof(struct dbl_limits); 260 i++, lim++) { 261 if ((id.mantissa2 == lim->ieee.mantissa2) && 262 (id.mantissa1 == lim->ieee.mantissa1) && 263 (id.exp == lim->ieee.exp)) { 264 vd = lim->d; 265 goto doneit; 266 } 267 } 268 vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; 269 vd.mantissa1 = (id.mantissa1 >> 13); 270 vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | 271 (id.mantissa2 >> 29); 272 vd.mantissa3 = (id.mantissa2 >> 13); 273 vd.mantissa4 = (id.mantissa2 << 3); 274 doneit: 275 vd.sign = id.sign; 276 *dp = *((double *)&vd); 277 return (TRUE); 278 #endif 279 280 case XDR_FREE: 281 return (TRUE); 282 } 283 return (FALSE); 284 } 285