1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 /* 30 * Portions of this source code were derived from Berkeley 31 * 4.3 BSD under license from the Regents of the University of 32 * California. 33 */ 34 35 #pragma ident "%Z%%M% %I% %E% SMI" 36 37 /* 38 * Generic XDR routines impelmentation. 39 * 40 * These are the "floating point" xdr routines used to (de)serialize 41 * most common data items. See xdr.h for more info on the interface to 42 * xdr. 43 */ 44 45 #include "mt.h" 46 #include <sys/types.h> 47 #include <stdio.h> 48 #include <rpc/types.h> 49 #include <rpc/xdr.h> 50 51 /* 52 * This routine works on Suns, 3b2, 68000s, 386 and Vaxen in a manner 53 * which is very efficient as bit twiddling is all that is needed. All 54 * other machines can use this code but the code is inefficient as 55 * various mathematical operations are used to generate the ieee format. 56 * In addition rounding errors may occur due to the calculations involved. 57 * To be most efficient, new machines should have their own ifdefs. 58 * The encoding routines will fail if the machines try to encode a 59 * float/double whose value can not be represented by the ieee format, 60 * e.g. the exponent is too big/small. 61 * ieee largest float = (2 ^ 128) * 0x1.fffff 62 * ieee smallest float = (2 ^ -127) * 0x1.00000 63 * ieee largest double = (2 ^ 1024) * 0x1.fffff 64 * ieee smallest double = (2 ^ -1023) * 0x1.00000 65 * The decoding routines assumes that the receiving machine can handle 66 * floats/doubles as large/small as the values stated above. If you 67 * use a machine which can not represent these values, you will need 68 * to put ifdefs in the decode sections to identify areas of failure. 69 */ 70 71 #if defined(vax) 72 73 /* 74 * What IEEE single precision floating point looks like this on a 75 * vax. 76 */ 77 78 struct ieee_single { 79 unsigned int mantissa: 23; 80 unsigned int exp : 8; 81 unsigned int sign : 1; 82 }; 83 84 #define IEEE_SNG_BIAS 0x7f 85 #define VAX_SNG_BIAS 0x81 86 87 88 /* Vax single precision floating point */ 89 struct vax_single { 90 unsigned int mantissa1 : 7; 91 unsigned int exp : 8; 92 unsigned int sign : 1; 93 unsigned int mantissa2 : 16; 94 }; 95 96 #define VAX_SNG_BIAS 0x81 97 98 static struct sgl_limits { 99 struct vax_single s; 100 struct ieee_single ieee; 101 } sgl_limits[2] = { 102 {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */ 103 { 0x0, 0xff, 0x0 }}, /* Max IEEE */ 104 {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */ 105 { 0x0, 0x0, 0x0 }} /* Min IEEE */ 106 }; 107 #endif /* vax */ 108 109 bool_t 110 xdr_float(XDR *xdrs, float *fp) 111 { 112 #if defined(vax) 113 struct ieee_single is; 114 struct vax_single vs, *vsp; 115 struct sgl_limits *lim; 116 size_t i; 117 #endif 118 119 switch (xdrs->x_op) { 120 121 case XDR_ENCODE: 122 #if defined(mc68000) || defined(sparc) || defined(u3b2) || \ 123 defined(u3b15) || defined(i386) || defined(amd64) 124 return (XDR_PUTINT32(xdrs, (int *)fp)); 125 #else 126 #if defined(vax) 127 vs = *((struct vax_single *)fp); 128 if ((vs.exp == 1) || (vs.exp == 2)) { 129 /* map these to subnormals */ 130 is.exp = 0; 131 is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; 132 /* lose some precision */ 133 is.mantissa >>= 3 - vs.exp; 134 is.mantissa += (1 << (20 + vs.exp)); 135 goto shipit; 136 } 137 for (i = 0, lim = sgl_limits; 138 i < (int)(sizeof (sgl_limits) / 139 sizeof (struct sgl_limits)); 140 i++, lim++) { 141 if ((vs.mantissa2 == lim->s.mantissa2) && 142 (vs.exp == lim->s.exp) && 143 (vs.mantissa1 == lim->s.mantissa1)) { 144 is = lim->ieee; 145 goto shipit; 146 } 147 } 148 is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; 149 is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; 150 shipit: 151 is.sign = vs.sign; 152 return (XDR_PUTINT32(xdrs, (int32_t *)&is)); 153 #else 154 { 155 /* 156 * Every machine can do this, its just not very efficient. 157 * In addtion, some rounding errors may occur do to the 158 * calculations involved. 159 */ 160 float f; 161 int neg = 0; 162 int exp = 0; 163 int32_t val; 164 165 f = *fp; 166 if (f == 0) { 167 val = 0; 168 return (XDR_PUTINT32(xdrs, &val)); 169 } 170 if (f < 0) { 171 f = 0 - f; 172 neg = 1; 173 } 174 while (f < 1) { 175 f = f * 2; 176 --exp; 177 } 178 while (f >= 2) { 179 f = f/2; 180 ++exp; 181 } 182 if ((exp > 128) || (exp < -127)) { 183 /* over or under flowing ieee exponent */ 184 return (FALSE); 185 } 186 val = neg; 187 val = val << 8; /* for the exponent */ 188 val += 127 + exp; /* 127 is the bias */ 189 val = val << 23; /* for the mantissa */ 190 val += (int32_t)((f - 1) * 8388608); /* 2 ^ 23 */ 191 return (XDR_PUTINT32(xdrs, &val)); 192 } 193 #endif 194 #endif 195 196 case XDR_DECODE: 197 #if defined(mc68000) || defined(sparc) || defined(u3b2) || \ 198 defined(u3b15) || defined(i386) || defined(amd64) 199 return (XDR_GETINT32(xdrs, (int *)fp)); 200 #else 201 #if defined(vax) 202 vsp = (struct vax_single *)fp; 203 if (!XDR_GETINT32(xdrs, (int32_t *)&is)) 204 return (FALSE); 205 206 for (i = 0, lim = sgl_limits; 207 i < (int)(sizeof (sgl_limits) / 208 sizeof (struct sgl_limits)); 209 i++, lim++) { 210 if ((is.exp == lim->ieee.exp) && 211 (is.mantissa == lim->ieee.mantissa)) { 212 *vsp = lim->s; 213 goto doneit; 214 } else if ((is.exp == 0) && (lim->ieee.exp == 0)) { 215 /* Special Case */ 216 unsigned tmp = is.mantissa >> 20; 217 if (tmp >= 4) { 218 vsp->exp = 2; 219 } else if (tmp >= 2) { 220 vsp->exp = 1; 221 } else { 222 *vsp = min.s; 223 break; 224 } /* else */ 225 tmp = is.mantissa - (1 << (20 + vsp->exp)); 226 tmp <<= 3 - vsp->exp; 227 vsp->mantissa2 = tmp; 228 vsp->mantissa1 = (tmp >> 16); 229 goto doneit; 230 } 231 vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; 232 vsp->mantissa2 = is.mantissa; 233 vsp->mantissa1 = (is.mantissa >> 16); 234 doneit: 235 vsp->sign = is.sign; 236 return (TRUE); 237 #else 238 { 239 /* 240 * Every machine can do this, its just not very 241 * efficient. It assumes that the decoding machine's 242 * float can represent any value in the range of 243 * ieee largest float = (2 ^ 128) * 0x1.fffff 244 * to 245 * ieee smallest float = (2 ^ -127) * 0x1.00000 246 * In addtion, some rounding errors may occur do to the 247 * calculations involved. 248 */ 249 float f; 250 int neg = 0; 251 int exp = 0; 252 int32_t val; 253 254 if (!XDR_GETINT32(xdrs, (int32_t *)&val)) 255 return (FALSE); 256 neg = val & 0x80000000; 257 exp = (val & 0x7f800000) >> 23; 258 exp -= 127; /* subtract exponent base */ 259 f = (val & 0x007fffff) * 0.00000011920928955078125; 260 /* 2 ^ -23 */ 261 f++; 262 while (exp != 0) { 263 if (exp < 0) { 264 f = f/2.0; 265 ++exp; 266 } else { 267 f = f * 2.0; 268 --exp; 269 } 270 } 271 if (neg) 272 f = 0 - f; 273 *fp = f; 274 } 275 return (TRUE); 276 #endif 277 #endif 278 279 case XDR_FREE: 280 return (TRUE); 281 } 282 return (FALSE); 283 } 284 285 /* 286 * This routine works on Suns (Sky / 68000's) and Vaxen. 287 */ 288 289 #if defined(vax) 290 /* What IEEE double precision floating point looks like on a Vax */ 291 struct ieee_double { 292 unsigned int mantissa1 : 20; 293 unsigned int exp : 11; 294 unsigned int sign : 1; 295 unsigned int mantissa2 : 32; 296 }; 297 298 /* Vax double precision floating point */ 299 struct vax_double { 300 unsigned int mantissa1 : 7; 301 unsigned int exp : 8; 302 unsigned int sign : 1; 303 unsigned int mantissa2 : 16; 304 unsigned int mantissa3 : 16; 305 unsigned int mantissa4 : 16; 306 }; 307 308 #define VAX_DBL_BIAS 0x81 309 #define IEEE_DBL_BIAS 0x3ff 310 #define MASK(nbits) ((1 << nbits) - 1) 311 312 static struct dbl_limits { 313 struct vax_double d; 314 struct ieee_double ieee; 315 } dbl_limits[2] = { 316 {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */ 317 { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */ 318 {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */ 319 { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */ 320 }; 321 322 #endif /* vax */ 323 324 325 bool_t 326 xdr_double(XDR *xdrs, double *dp) 327 { 328 int *lp; 329 #if defined(vax) 330 struct ieee_double id; 331 struct vax_double vd; 332 struct dbl_limits *lim; 333 size_t i; 334 #endif 335 336 switch (xdrs->x_op) { 337 338 case XDR_ENCODE: 339 #if defined(mc68000) || defined(u3b2) || defined(u3b15) || \ 340 defined(_LONG_LONG_HTOL) 341 lp = (int *)dp; 342 return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp)); 343 #else 344 #if defined(_LONG_LONG_LTOH) 345 lp = (int *)dp; 346 lp++; 347 return (XDR_PUTINT32(xdrs, lp--) && XDR_PUTINT32(xdrs, lp)); 348 #else 349 #if defined(vax) 350 vd = *((struct vax_double *)dp); 351 for (i = 0, lim = dbl_limits; 352 i < (int)(sizeof (dbl_limits) / 353 sizeof (struct dbl_limits)); 354 i++, lim++) { 355 if ((vd.mantissa4 == lim->d.mantissa4) && 356 (vd.mantissa3 == lim->d.mantissa3) && 357 (vd.mantissa2 == lim->d.mantissa2) && 358 (vd.mantissa1 == lim->d.mantissa1) && 359 (vd.exp == lim->d.exp)) { 360 id = lim->ieee; 361 goto shipit; 362 } 363 } 364 id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS; 365 id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3); 366 id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) | 367 (vd.mantissa3 << 13) | 368 ((vd.mantissa4 >> 3) & MASK(13)); 369 shipit: 370 id.sign = vd.sign; 371 lp = (int32_t *)&id; 372 #else 373 { 374 /* 375 * Every machine can do this, its just not very efficient. 376 * In addtion, some rounding errors may occur do to the 377 * calculations involved. 378 */ 379 double d; 380 int neg = 0; 381 int exp = 0; 382 int32_t val[2]; 383 384 d = *dp; 385 if (d == 0) { 386 val[0] = 0; 387 val[1] = 0; 388 lp = val; 389 return (XDR_PUTINT32(xdrs, lp++) && 390 XDR_PUTINT32(xdrs, lp)); 391 } 392 if (d < 0) { 393 d = 0 - d; 394 neg = 1; 395 } 396 while (d < 1) { 397 d = d * 2; 398 --exp; 399 } 400 while (d >= 2) { 401 d = d/2; 402 ++exp; 403 } 404 if ((exp > 1024) || (exp < -1023)) { 405 /* over or under flowing ieee exponent */ 406 return (FALSE); 407 } 408 val[0] = neg; 409 val[0] = val[0] << 11; /* for the exponent */ 410 val[0] += 1023 + exp; /* 1023 is the bias */ 411 val[0] = val[0] << 20; /* for the mantissa */ 412 val[0] += (int32_t)((d - 1) * 1048576); /* 2 ^ 20 */ 413 val[1] += (int32_t)((((d - 1) * 1048576) - val[0]) 414 * 4294967296); 415 /* 2 ^ 32 */ 416 lp = val; 417 } 418 #endif 419 return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp)); 420 #endif 421 #endif 422 423 case XDR_DECODE: 424 #if defined(mc68000) || defined(u3b2) || defined(u3b15) || \ 425 defined(_LONG_LONG_HTOL) 426 lp = (int *)dp; 427 return (XDR_GETINT32(xdrs, lp++) && XDR_GETINT32(xdrs, lp)); 428 #else 429 #if defined(_LONG_LONG_LTOH) 430 lp = (int *)dp; 431 lp++; 432 return (XDR_GETINT32(xdrs, lp--) && XDR_GETINT32(xdrs, lp)); 433 #else 434 #if defined(vax) 435 lp = (int32_t *)&id; 436 if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp)) 437 return (FALSE); 438 for (i = 0, lim = dbl_limits; 439 i < sizeof (dbl_limits)/sizeof (struct dbl_limits); 440 i++, lim++) { 441 if ((id.mantissa2 == lim->ieee.mantissa2) && 442 (id.mantissa1 == lim->ieee.mantissa1) && 443 (id.exp == lim->ieee.exp)) { 444 vd = lim->d; 445 goto doneit; 446 } 447 } 448 vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; 449 vd.mantissa1 = (id.mantissa1 >> 13); 450 vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | 451 (id.mantissa2 >> 29); 452 vd.mantissa3 = (id.mantissa2 >> 13); 453 vd.mantissa4 = (id.mantissa2 << 3); 454 doneit: 455 vd.sign = id.sign; 456 *dp = *((double *)&vd); 457 return (TRUE); 458 #else 459 { 460 /* 461 * Every machine can do this, its just not very 462 * efficient. It assumes that the decoding machine's 463 * double can represent any value in the range of 464 * ieee largest double = (2 ^ 1024) * 0x1.fffffffffffff 465 * to 466 * ieee smallest double = (2 ^ -1023) * 0x1.0000000000000 467 * In addtion, some rounding errors may occur do to the 468 * calculations involved. 469 */ 470 double d; 471 int neg = 0; 472 int exp = 0; 473 int32_t val[2]; 474 475 lp = val; 476 if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp)) 477 return (FALSE); 478 neg = val[0] & 0x80000000; 479 exp = (val[0] & 0x7ff00000) >> 20; 480 exp -= 1023; /* subtract exponent base */ 481 d = (val[0] & 0x000fffff) * 0.00000095367431640625; 482 /* 2 ^ -20 */ 483 d += (val[1] * 0.0000000000000002220446049250313); 484 /* 2 ^ -52 */ 485 d++; 486 while (exp != 0) { 487 if (exp < 0) { 488 d = d/2.0; 489 ++exp; 490 } else { 491 d = d * 2.0; 492 --exp; 493 } 494 } 495 if (neg) 496 d = 0 - d; 497 *dp = d; 498 } 499 #endif 500 #endif 501 #endif 502 503 case XDR_FREE: 504 return (TRUE); 505 } 506 return (FALSE); 507 } 508 509 /* ARGSUSED */ 510 bool_t 511 xdr_quadruple(XDR *xdrs, long double *fp) 512 { 513 /* 514 * The Sparc uses IEEE FP encoding, so just do a byte copy 515 */ 516 517 #if !defined(sparc) 518 return (FALSE); 519 #else 520 switch (xdrs->x_op) { 521 case XDR_ENCODE: 522 return (XDR_PUTBYTES(xdrs, (char *)fp, sizeof (long double))); 523 case XDR_DECODE: 524 return (XDR_GETBYTES(xdrs, (char *)fp, sizeof (long double))); 525 case XDR_FREE: 526 return (TRUE); 527 } 528 return (FALSE); 529 #endif 530 } 531