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