|
|
1.1 ! root 1: /* atof_ieee.c - turn a Flonum into an IEEE floating point number ! 2: Copyright (C) 1987 Free Software Foundation, Inc. ! 3: ! 4: This file is part of GAS, the GNU Assembler. ! 5: ! 6: GAS is free software; you can redistribute it and/or modify ! 7: it under the terms of the GNU General Public License as published by ! 8: the Free Software Foundation; either version 1, or (at your option) ! 9: any later version. ! 10: ! 11: GAS is distributed in the hope that it will be useful, ! 12: but WITHOUT ANY WARRANTY; without even the implied warranty of ! 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ! 14: GNU General Public License for more details. ! 15: ! 16: You should have received a copy of the GNU General Public License ! 17: along with GAS; see the file COPYING. If not, write to ! 18: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ ! 19: ! 20: #include "flonum.h" ! 21: #ifdef USG ! 22: #define bzero(s,n) memset(s,0,n) ! 23: #define bcopy(from,to,n) memcpy((to),(from),(n)) ! 24: #endif ! 25: ! 26: extern FLONUM_TYPE generic_floating_point_number; /* Flonums returned here. */ ! 27: #define NULL (0) ! 28: ! 29: extern char EXP_CHARS[]; ! 30: /* Precision in LittleNums. */ ! 31: #define MAX_PRECISION (6) ! 32: #define F_PRECISION (2) ! 33: #define D_PRECISION (4) ! 34: #define X_PRECISION (6) ! 35: #define P_PRECISION (6) ! 36: ! 37: /* Length in LittleNums of guard bits. */ ! 38: #define GUARD (2) ! 39: ! 40: static unsigned long int mask [] = { ! 41: 0x00000000, ! 42: 0x00000001, ! 43: 0x00000003, ! 44: 0x00000007, ! 45: 0x0000000f, ! 46: 0x0000001f, ! 47: 0x0000003f, ! 48: 0x0000007f, ! 49: 0x000000ff, ! 50: 0x000001ff, ! 51: 0x000003ff, ! 52: 0x000007ff, ! 53: 0x00000fff, ! 54: 0x00001fff, ! 55: 0x00003fff, ! 56: 0x00007fff, ! 57: 0x0000ffff, ! 58: 0x0001ffff, ! 59: 0x0003ffff, ! 60: 0x0007ffff, ! 61: 0x000fffff, ! 62: 0x001fffff, ! 63: 0x003fffff, ! 64: 0x007fffff, ! 65: 0x00ffffff, ! 66: 0x01ffffff, ! 67: 0x03ffffff, ! 68: 0x07ffffff, ! 69: 0x0fffffff, ! 70: 0x1fffffff, ! 71: 0x3fffffff, ! 72: 0x7fffffff, ! 73: 0xffffffff ! 74: }; ! 75: ! 76: static int bits_left_in_littlenum; ! 77: static int littlenums_left; ! 78: static LITTLENUM_TYPE * littlenum_pointer; ! 79: ! 80: static int ! 81: next_bits (number_of_bits) ! 82: int number_of_bits; ! 83: { ! 84: int return_value; ! 85: ! 86: if(!littlenums_left) ! 87: return 0; ! 88: if (number_of_bits >= bits_left_in_littlenum) ! 89: { ! 90: return_value = mask [bits_left_in_littlenum] & *littlenum_pointer; ! 91: number_of_bits -= bits_left_in_littlenum; ! 92: return_value <<= number_of_bits; ! 93: if(--littlenums_left) { ! 94: bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS - number_of_bits; ! 95: littlenum_pointer --; ! 96: return_value |= (*littlenum_pointer>>bits_left_in_littlenum) & mask[number_of_bits]; ! 97: } ! 98: } ! 99: else ! 100: { ! 101: bits_left_in_littlenum -= number_of_bits; ! 102: return_value = mask [number_of_bits] & (*littlenum_pointer>>bits_left_in_littlenum); ! 103: } ! 104: return (return_value); ! 105: } ! 106: ! 107: /* Num had better be less than LITTLENUM_NUMBER_OF_BITS */ ! 108: static int ! 109: unget_bits(num) ! 110: { ! 111: if(!littlenums_left) { ! 112: ++littlenum_pointer; ! 113: ++littlenums_left; ! 114: bits_left_in_littlenum=num; ! 115: } else if(bits_left_in_littlenum+num>LITTLENUM_NUMBER_OF_BITS) { ! 116: bits_left_in_littlenum= num-(LITTLENUM_NUMBER_OF_BITS-bits_left_in_littlenum); ! 117: ++littlenum_pointer; ! 118: ++littlenums_left; ! 119: } else ! 120: bits_left_in_littlenum+=num; ! 121: } ! 122: ! 123: static void ! 124: make_invalid_floating_point_number (words) ! 125: LITTLENUM_TYPE * words; ! 126: { ! 127: as_warn("cannot create floating-point number"); ! 128: words[0]= ((unsigned)-1)>>1; /* Zero the leftmost bit */ ! 129: words[1]= -1; ! 130: words[2]= -1; ! 131: words[3]= -1; ! 132: words[4]= -1; ! 133: words[5]= -1; ! 134: } ! 135: ! 136: /***********************************************************************\ ! 137: * Warning: this returns 16-bit LITTLENUMs. It is up to the caller * ! 138: * to figure out any alignment problems and to conspire for the * ! 139: * bytes/word to be emitted in the right order. Bigendians beware! * ! 140: * * ! 141: \***********************************************************************/ ! 142: ! 143: /* Note that atof-ieee always has X and P precisions enabled. it is up ! 144: to md_atof to filter them out if the target machine does not support ! 145: them. */ ! 146: ! 147: char * /* Return pointer past text consumed. */ ! 148: atof_ieee (str, what_kind, words) ! 149: char * str; /* Text to convert to binary. */ ! 150: char what_kind; /* 'd', 'f', 'g', 'h' */ ! 151: LITTLENUM_TYPE * words; /* Build the binary here. */ ! 152: { ! 153: static LITTLENUM_TYPE bits [MAX_PRECISION + MAX_PRECISION + GUARD]; ! 154: /* Extra bits for zeroed low-order bits. */ ! 155: /* The 1st MAX_PRECISION are zeroed, */ ! 156: /* the last contain flonum bits. */ ! 157: char * return_value; ! 158: int precision; /* Number of 16-bit words in the format. */ ! 159: long int exponent_bits; ! 160: ! 161: return_value = str; ! 162: generic_floating_point_number.low = bits + MAX_PRECISION; ! 163: generic_floating_point_number.high = NULL; ! 164: generic_floating_point_number.leader = NULL; ! 165: generic_floating_point_number.exponent = NULL; ! 166: generic_floating_point_number.sign = '\0'; ! 167: ! 168: /* Use more LittleNums than seems */ ! 169: /* necessary: the highest flonum may have */ ! 170: /* 15 leading 0 bits, so could be useless. */ ! 171: ! 172: bzero (bits, sizeof(LITTLENUM_TYPE) * MAX_PRECISION); ! 173: ! 174: switch(what_kind) { ! 175: case 'f': ! 176: case 'F': ! 177: case 's': ! 178: case 'S': ! 179: precision = F_PRECISION; ! 180: exponent_bits = 8; ! 181: break; ! 182: ! 183: case 'd': ! 184: case 'D': ! 185: case 'r': ! 186: case 'R': ! 187: precision = D_PRECISION; ! 188: exponent_bits = 11; ! 189: break; ! 190: ! 191: case 'x': ! 192: case 'X': ! 193: case 'e': ! 194: case 'E': ! 195: precision = X_PRECISION; ! 196: exponent_bits = 15; ! 197: break; ! 198: ! 199: case 'p': ! 200: case 'P': ! 201: ! 202: precision = P_PRECISION; ! 203: exponent_bits= -1; ! 204: break; ! 205: ! 206: default: ! 207: make_invalid_floating_point_number (words); ! 208: return NULL; ! 209: } ! 210: ! 211: generic_floating_point_number.high = generic_floating_point_number.low + precision - 1 + GUARD; ! 212: ! 213: if (atof_generic (& return_value, ".", EXP_CHARS, & generic_floating_point_number)) { ! 214: /* as_warn("Error converting floating point number (Exponent overflow?)"); */ ! 215: make_invalid_floating_point_number (words); ! 216: return NULL; ! 217: } ! 218: gen_to_words(words, precision, exponent_bits); ! 219: return return_value; ! 220: } ! 221: ! 222: /* Turn generic_floating_point_number into a real float/double/extended */ ! 223: gen_to_words(words,precision,exponent_bits) ! 224: LITTLENUM_TYPE *words; ! 225: long int exponent_bits; ! 226: int precision; ! 227: { ! 228: int return_value=0; ! 229: ! 230: long int exponent_1; ! 231: long int exponent_2; ! 232: long int exponent_3; ! 233: long int exponent_4; ! 234: int exponent_skippage; ! 235: LITTLENUM_TYPE word1; ! 236: LITTLENUM_TYPE * lp; ! 237: ! 238: if (generic_floating_point_number.low > generic_floating_point_number.leader) { ! 239: /* 0.0e0 seen. */ ! 240: if(generic_floating_point_number.sign=='+') ! 241: words[0]=0x0000; ! 242: else ! 243: words[0]=0x8000; ! 244: bzero (&words[1], sizeof(LITTLENUM_TYPE) * (precision-1)); ! 245: return return_value; ! 246: } ! 247: ! 248: /* NaN: Do the right thing */ ! 249: if(generic_floating_point_number.sign==0) { ! 250: if(precision==F_PRECISION) { ! 251: words[0]=0x7fff; ! 252: words[1]=0xffff; ! 253: } else { ! 254: words[0]=0x7fff; ! 255: words[1]=0xffff; ! 256: words[2]=0xffff; ! 257: words[3]=0xffff; ! 258: } ! 259: return return_value; ! 260: } else if(generic_floating_point_number.sign=='P') { ! 261: /* +INF: Do the right thing */ ! 262: if(precision==F_PRECISION) { ! 263: words[0]=0x7f80; ! 264: words[1]=0; ! 265: } else { ! 266: words[0]=0x7ff0; ! 267: words[1]=0; ! 268: words[2]=0; ! 269: words[3]=0; ! 270: } ! 271: return return_value; ! 272: } else if(generic_floating_point_number.sign=='N') { ! 273: /* Negative INF */ ! 274: if(precision==F_PRECISION) { ! 275: words[0]=0xff80; ! 276: words[1]=0x0; ! 277: } else { ! 278: words[0]=0xfff0; ! 279: words[1]=0x0; ! 280: words[2]=0x0; ! 281: words[3]=0x0; ! 282: } ! 283: return return_value; ! 284: } ! 285: /* ! 286: * The floating point formats we support have: ! 287: * Bit 15 is sign bit. ! 288: * Bits 14:n are excess-whatever exponent. ! 289: * Bits n-1:0 (if any) are most significant bits of fraction. ! 290: * Bits 15:0 of the next word(s) are the next most significant bits. ! 291: * ! 292: * So we need: number of bits of exponent, number of bits of ! 293: * mantissa. ! 294: */ ! 295: bits_left_in_littlenum = LITTLENUM_NUMBER_OF_BITS; ! 296: littlenum_pointer = generic_floating_point_number.leader; ! 297: littlenums_left = 1+generic_floating_point_number.leader - generic_floating_point_number.low; ! 298: /* Seek (and forget) 1st significant bit */ ! 299: for (exponent_skippage = 0;! next_bits(1); exponent_skippage ++) ! 300: ; ! 301: exponent_1 = generic_floating_point_number.exponent + generic_floating_point_number.leader + 1 - ! 302: generic_floating_point_number.low; ! 303: /* Radix LITTLENUM_RADIX, point just higher than generic_floating_point_number.leader. */ ! 304: exponent_2 = exponent_1 * LITTLENUM_NUMBER_OF_BITS; ! 305: /* Radix 2. */ ! 306: exponent_3 = exponent_2 - exponent_skippage; ! 307: /* Forget leading zeros, forget 1st bit. */ ! 308: exponent_4 = exponent_3 + ((1 << (exponent_bits - 1)) - 2); ! 309: /* Offset exponent. */ ! 310: ! 311: lp = words; ! 312: ! 313: /* Word 1. Sign, exponent and perhaps high bits. */ ! 314: word1 = (generic_floating_point_number.sign == '+') ? 0 : (1<<(LITTLENUM_NUMBER_OF_BITS-1)); ! 315: ! 316: /* Assume 2's complement integers. */ ! 317: if(exponent_4<1 && exponent_4>=-62) { ! 318: int prec_bits; ! 319: int num_bits; ! 320: ! 321: unget_bits(1); ! 322: num_bits= -exponent_4; ! 323: prec_bits=LITTLENUM_NUMBER_OF_BITS*precision-(exponent_bits+1+num_bits); ! 324: if(precision==X_PRECISION && exponent_bits==15) ! 325: prec_bits-=LITTLENUM_NUMBER_OF_BITS+1; ! 326: ! 327: if(num_bits>=LITTLENUM_NUMBER_OF_BITS-exponent_bits) { ! 328: /* Bigger than one littlenum */ ! 329: num_bits-=(LITTLENUM_NUMBER_OF_BITS-1)-exponent_bits; ! 330: *lp++=word1; ! 331: if(num_bits+exponent_bits+1>=precision*LITTLENUM_NUMBER_OF_BITS) { ! 332: /* Exponent overflow */ ! 333: make_invalid_floating_point_number(words); ! 334: return return_value; ! 335: } ! 336: if(precision==X_PRECISION && exponent_bits==15) { ! 337: *lp++=0; ! 338: *lp++=0; ! 339: num_bits-=LITTLENUM_NUMBER_OF_BITS-1; ! 340: } ! 341: while(num_bits>=LITTLENUM_NUMBER_OF_BITS) { ! 342: num_bits-=LITTLENUM_NUMBER_OF_BITS; ! 343: *lp++=0; ! 344: } ! 345: if(num_bits) ! 346: *lp++=next_bits(LITTLENUM_NUMBER_OF_BITS-(num_bits)); ! 347: } else { ! 348: if(precision==X_PRECISION && exponent_bits==15) { ! 349: *lp++=word1; ! 350: *lp++=0; ! 351: if(num_bits==LITTLENUM_NUMBER_OF_BITS) { ! 352: *lp++=0; ! 353: *lp++=next_bits(LITTLENUM_NUMBER_OF_BITS-1); ! 354: } else if(num_bits==LITTLENUM_NUMBER_OF_BITS-1) ! 355: *lp++=0; ! 356: else ! 357: *lp++=next_bits(LITTLENUM_NUMBER_OF_BITS-1-num_bits); ! 358: num_bits=0; ! 359: } else { ! 360: word1|= next_bits ((LITTLENUM_NUMBER_OF_BITS-1) - (exponent_bits+num_bits)); ! 361: *lp++=word1; ! 362: } ! 363: } ! 364: while(lp<words+precision) ! 365: *lp++=next_bits(LITTLENUM_NUMBER_OF_BITS); ! 366: ! 367: /* Round the mantissa up, but don't change the number */ ! 368: if(next_bits(1)) { ! 369: --lp; ! 370: if(prec_bits>LITTLENUM_NUMBER_OF_BITS) { ! 371: int n = 0; ! 372: int tmp_bits; ! 373: ! 374: n=0; ! 375: tmp_bits=prec_bits; ! 376: while(tmp_bits>LITTLENUM_NUMBER_OF_BITS) { ! 377: if(lp[n]!=(LITTLENUM_TYPE)-1) ! 378: break; ! 379: --n; ! 380: tmp_bits-=LITTLENUM_NUMBER_OF_BITS; ! 381: } ! 382: if(tmp_bits>LITTLENUM_NUMBER_OF_BITS || (lp[n]&mask[tmp_bits])!=mask[tmp_bits]) { ! 383: unsigned long int carry; ! 384: ! 385: for (carry = 1; carry && (lp >= words); lp --) { ! 386: carry = * lp + carry; ! 387: * lp = carry; ! 388: carry >>= LITTLENUM_NUMBER_OF_BITS; ! 389: } ! 390: } ! 391: } else if((*lp&mask[prec_bits])!=mask[prec_bits]) ! 392: lp++; ! 393: } ! 394: ! 395: return return_value; ! 396: } else if (exponent_4 & ~ mask [exponent_bits]) { ! 397: /* ! 398: * Exponent overflow. Lose immediately. ! 399: */ ! 400: ! 401: /* ! 402: * We leave return_value alone: admit we read the ! 403: * number, but return a floating exception ! 404: * because we can't encode the number. ! 405: */ ! 406: make_invalid_floating_point_number (words); ! 407: return return_value; ! 408: } else { ! 409: word1 |= (exponent_4 << ((LITTLENUM_NUMBER_OF_BITS-1) - exponent_bits)) ! 410: | next_bits ((LITTLENUM_NUMBER_OF_BITS-1) - exponent_bits); ! 411: } ! 412: ! 413: * lp ++ = word1; ! 414: ! 415: /* X_PRECISION is special: it has 16 bits of zero in the middle, ! 416: followed by a 1 bit. */ ! 417: if(exponent_bits==15 && precision==X_PRECISION) { ! 418: *lp++=0; ! 419: *lp++= 1<<(LITTLENUM_NUMBER_OF_BITS)|next_bits(LITTLENUM_NUMBER_OF_BITS-1); ! 420: } ! 421: ! 422: /* The rest of the words are just mantissa bits. */ ! 423: while(lp < words + precision) ! 424: *lp++ = next_bits (LITTLENUM_NUMBER_OF_BITS); ! 425: ! 426: if (next_bits (1)) { ! 427: unsigned long int carry; ! 428: /* ! 429: * Since the NEXT bit is a 1, round UP the mantissa. ! 430: * The cunning design of these hidden-1 floats permits ! 431: * us to let the mantissa overflow into the exponent, and ! 432: * it 'does the right thing'. However, we lose if the ! 433: * highest-order bit of the lowest-order word flips. ! 434: * Is that clear? ! 435: */ ! 436: ! 437: ! 438: /* #if (sizeof(carry)) < ((sizeof(bits[0]) * BITS_PER_CHAR) + 2) ! 439: Please allow at least 1 more bit in carry than is in a LITTLENUM. ! 440: We need that extra bit to hold a carry during a LITTLENUM carry ! 441: propagation. Another extra bit (kept 0) will assure us that we ! 442: don't get a sticky sign bit after shifting right, and that ! 443: permits us to propagate the carry without any masking of bits. ! 444: #endif */ ! 445: for (carry = 1, lp --; carry && (lp >= words); lp --) { ! 446: carry = * lp + carry; ! 447: * lp = carry; ! 448: carry >>= LITTLENUM_NUMBER_OF_BITS; ! 449: } ! 450: if ( (word1 ^ *words) & (1 << (LITTLENUM_NUMBER_OF_BITS - 1)) ) { ! 451: /* We leave return_value alone: admit we read the ! 452: * number, but return a floating exception ! 453: * because we can't encode the number. ! 454: */ ! 455: *words&= ~ (1 << (LITTLENUM_NUMBER_OF_BITS - 1)); ! 456: /* make_invalid_floating_point_number (words); */ ! 457: /* return return_value; */ ! 458: } ! 459: } ! 460: return (return_value); ! 461: } ! 462: ! 463: /* This routine is a real kludge. Someone really should do it better, but ! 464: I'm too lazy, and I don't understand this stuff all too well anyway ! 465: (JF) ! 466: */ ! 467: void ! 468: int_to_gen(x) ! 469: long x; ! 470: { ! 471: char buf[20]; ! 472: char *bufp; ! 473: ! 474: sprintf(buf,"%ld",x); ! 475: bufp= &buf[0]; ! 476: if(atof_generic(&bufp,".", EXP_CHARS, &generic_floating_point_number)) ! 477: as_warn("Error converting number to floating point (Exponent overflow?)"); ! 478: } ! 479: ! 480: #ifdef TEST ! 481: char * ! 482: print_gen(gen) ! 483: FLONUM_TYPE *gen; ! 484: { ! 485: FLONUM_TYPE f; ! 486: LITTLENUM_TYPE arr[10]; ! 487: double dv; ! 488: float fv; ! 489: static char sbuf[40]; ! 490: ! 491: if(gen) { ! 492: f=generic_floating_point_number; ! 493: generic_floating_point_number= *gen; ! 494: } ! 495: gen_to_words(&arr[0],4,11); ! 496: bcopy(&arr[0],&dv,sizeof(double)); ! 497: sprintf(sbuf,"%x %x %x %x %.14G ",arr[0],arr[1],arr[2],arr[3],dv); ! 498: gen_to_words(&arr[0],2,8); ! 499: bcopy(&arr[0],&fv,sizeof(float)); ! 500: sprintf(sbuf+strlen(sbuf),"%x %x %.12g\n",arr[0],arr[1],fv); ! 501: if(gen) ! 502: generic_floating_point_number=f; ! 503: return sbuf; ! 504: } ! 505: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.