float.c
上传用户:yuppie_zhu
上传日期:2007-01-08
资源大小:535k
文件大小:10k
源码类别:

编译器/解释器

开发平台:

C/C++

  1. /* float.c     floating-point constant support for the Netwide Assembler
  2.  *
  3.  * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  4.  * Julian Hall. All rights reserved. The software is
  5.  * redistributable under the licence given in the file "Licence"
  6.  * distributed in the NASM archive.
  7.  *
  8.  * initial version 13/ix/96 by Simon Tatham
  9.  */
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include "nasm.h"
  14. #define TRUE 1
  15. #define FALSE 0
  16. #define MANT_WORDS 6        /* 64 bits + 32 for accuracy == 96 */
  17. #define MANT_DIGITS 28        /* 29 digits don't fit in 96 bits */
  18. /*
  19.  * guaranteed top bit of from is set
  20.  * => we only have to worry about _one_ bit shift to the left
  21.  */
  22. static int multiply(unsigned short *to, unsigned short *from) 
  23. {
  24.     unsigned long temp[MANT_WORDS*2];
  25.     int           i, j;
  26.     for (i=0; i<MANT_WORDS*2; i++)
  27. temp[i] = 0;
  28.     for (i=0; i<MANT_WORDS; i++)
  29. for (j=0; j<MANT_WORDS; j++) {
  30.     unsigned long n;
  31.     n = (unsigned long)to[i] * (unsigned long)from[j];
  32.     temp[i+j] += n >> 16;
  33.     temp[i+j+1] += n & 0xFFFF;
  34. }
  35.     for (i=MANT_WORDS*2; --i ;) {
  36. temp[i-1] += temp[i] >> 16;
  37. temp[i] &= 0xFFFF;
  38.     }
  39.     if (temp[0] & 0x8000) {
  40. for (i=0; i<MANT_WORDS; i++)
  41.     to[i] = temp[i] & 0xFFFF;
  42. return 0;
  43.     } else {
  44. for (i=0; i<MANT_WORDS; i++)
  45.     to[i] = (temp[i] << 1) + !!(temp[i+1] & 0x8000);
  46. return -1;
  47.     }
  48. }
  49. static void flconvert(char *string, unsigned short *mant, long *exponent,
  50.       efunc error) 
  51. {
  52.     char           digits[MANT_DIGITS];
  53.     char           *p, *q, *r;
  54.     unsigned short mult[MANT_WORDS], bit;
  55.     unsigned short * m;
  56.     long           tenpwr, twopwr;
  57.     int            extratwos, started, seendot;
  58.     p = digits;
  59.     tenpwr = 0;
  60.     started = seendot = FALSE;
  61.     while (*string && *string != 'E' && *string != 'e') {
  62. if (*string == '.') {
  63.     if (!seendot)
  64. seendot = TRUE;
  65.     else {
  66. error (ERR_NONFATAL,
  67.        "too many periods in floating-point constant");
  68. return;
  69.     }
  70. } else if (*string >= '0' && *string <= '9') {
  71.     if (*string == '0' && !started) {
  72. if (seendot)
  73.     tenpwr--;
  74.     } else {
  75. started = TRUE;
  76. if (p < digits+sizeof(digits))
  77.     *p++ = *string - '0';
  78. if (!seendot)
  79.     tenpwr++;
  80.     }
  81. } else {
  82.     error (ERR_NONFATAL,
  83.    "floating-point constant: `%c' is invalid character",
  84.    *string);
  85.     return;
  86. }
  87. string++;
  88.     }
  89.     if (*string) {
  90. string++;        /* eat the E */
  91. tenpwr += atoi(string);
  92.     }
  93.     /*
  94.      * At this point, the memory interval [digits,p) contains a
  95.      * series of decimal digits zzzzzzz such that our number X
  96.      * satisfies
  97.      *
  98.      * X = 0.zzzzzzz * 10^tenpwr
  99.      */
  100.     bit = 0x8000;
  101.     for (m=mant; m<mant+MANT_WORDS; m++)
  102. *m = 0;
  103.     m = mant;
  104.     q = digits;
  105.     started = FALSE;
  106.     twopwr = 0;
  107.     while (m < mant+MANT_WORDS) {
  108. unsigned short carry = 0;
  109. while (p > q && !p[-1])
  110.     p--;
  111. if (p <= q)
  112.     break;
  113. for (r = p; r-- > q ;) {
  114.     int i;
  115.     i = 2 * *r + carry;
  116.     if (i >= 10)
  117. carry = 1, i -= 10;
  118.     else
  119. carry = 0;
  120.     *r = i;
  121. }
  122. if (carry)
  123.     *m |= bit, started = TRUE;
  124. if (started) {
  125.     if (bit == 1)
  126. bit = 0x8000, m++;
  127.     else
  128. bit >>= 1;
  129. } else
  130.     twopwr--;
  131.     }
  132.     twopwr += tenpwr;
  133.     /*
  134.      * At this point the `mant' array contains the first six
  135.      * fractional places of a base-2^16 real number, which when
  136.      * multiplied by 2^twopwr and 5^tenpwr gives X. So now we
  137.      * really do multiply by 5^tenpwr.
  138.      */
  139.     if (tenpwr < 0) {
  140. for (m=mult; m<mult+MANT_WORDS; m++)
  141.     *m = 0xCCCC;
  142. extratwos = -2;
  143. tenpwr = -tenpwr;
  144.     } else if (tenpwr > 0) {
  145. mult[0] = 0xA000;
  146. for (m=mult+1; m<mult+MANT_WORDS; m++)
  147.     *m = 0;
  148. extratwos = 3;
  149.     } else
  150. extratwos = 0;
  151.     while (tenpwr) {
  152. if (tenpwr & 1)
  153.     twopwr += extratwos + multiply (mant, mult);
  154. extratwos = extratwos * 2 + multiply (mult, mult);
  155. tenpwr >>= 1;
  156.     }
  157.     /*
  158.      * Conversion is done. The elements of `mant' contain the first
  159.      * fractional places of a base-2^16 real number in [0.5,1)
  160.      * which we can multiply by 2^twopwr to get X. Or, of course,
  161.      * it contains zero.
  162.      */
  163.     *exponent = twopwr;
  164. }
  165. /*
  166.  * Shift a mantissa to the right by i (i < 16) bits.
  167.  */
  168. static void shr(unsigned short *mant, int i) 
  169. {
  170.     unsigned short n = 0, m;
  171.     int            j;
  172.     for (j=0; j<MANT_WORDS; j++) {
  173. m = (mant[j] << (16-i)) & 0xFFFF;
  174. mant[j] = (mant[j] >> i) | n;
  175. n = m;
  176.     }
  177. }
  178. /*
  179.  * Round a mantissa off after i words.
  180.  */
  181. static int round(unsigned short *mant, int i) 
  182. {
  183.     if (mant[i] & 0x8000) {
  184. do {
  185.     ++mant[--i];
  186.     mant[i] &= 0xFFFF;
  187. } while (i > 0 && !mant[i]);
  188. return !i && !mant[i];
  189.     }
  190.     return 0;
  191. }
  192. #define put(a,b) ( (*(a)=(b)), ((a)[1]=(b)>>8) )
  193. static int to_double(char *str, long sign, unsigned char *result,
  194.      efunc error) 
  195. {
  196.     unsigned short mant[MANT_WORDS];
  197.     long exponent;
  198.     sign = (sign < 0 ? 0x8000L : 0L);
  199.     flconvert (str, mant, &exponent, error);
  200.     if (mant[0] & 0x8000) {
  201. /*
  202.  * Non-zero.
  203.  */
  204. exponent--;
  205. if (exponent >= -1022 && exponent <= 1024) {
  206.     /*
  207.      * Normalised.
  208.      */
  209.     exponent += 1023;
  210.     shr(mant, 11);
  211.     round(mant, 4);
  212.     if (mant[0] & 0x20)        /* did we scale up by one? */
  213. shr(mant, 1), exponent++;
  214.     mant[0] &= 0xF;        /* remove leading one */
  215.     put(result+6,(exponent << 4) | mant[0] | sign);
  216.     put(result+4,mant[1]);
  217.     put(result+2,mant[2]);
  218.     put(result+0,mant[3]);
  219. } else if (exponent < -1022 && exponent >= -1074) {
  220.     /*
  221.      * Denormal.
  222.      */
  223.     int shift = -(exponent+1011);
  224.     int sh = shift % 16, wds = shift / 16;
  225.     shr(mant, sh);
  226.     if (round(mant, 4-wds) || (sh>0 && (mant[0]&(0x8000>>(sh-1))))) {
  227. shr(mant, 1);
  228. if (sh==0)
  229.     mant[0] |= 0x8000;
  230. exponent++;
  231.     }
  232.     put(result+6,(wds == 0 ? mant[0] : 0) | sign);
  233.     put(result+4,(wds <= 1 ? mant[1-wds] : 0));
  234.     put(result+2,(wds <= 2 ? mant[2-wds] : 0));
  235.     put(result+0,(wds <= 3 ? mant[3-wds] : 0));
  236. } else {
  237.     if (exponent > 0) {
  238. error(ERR_NONFATAL, "overflow in floating-point constant");
  239. return 0;
  240.     } else
  241. memset (result, 0, 8);
  242. }
  243.     } else {
  244. /*
  245.  * Zero.
  246.  */
  247. memset (result, 0, 8);
  248.     }
  249.     return 1;        /* success */
  250. }
  251. static int to_float(char *str, long sign, unsigned char *result,
  252.     efunc error) 
  253. {
  254.     unsigned short mant[MANT_WORDS];
  255.     long exponent;
  256.     sign = (sign < 0 ? 0x8000L : 0L);
  257.     flconvert (str, mant, &exponent, error);
  258.     if (mant[0] & 0x8000) {
  259. /*
  260.  * Non-zero.
  261.  */
  262. exponent--;
  263. if (exponent >= -126 && exponent <= 128) {
  264.     /*
  265.      * Normalised.
  266.      */
  267.     exponent += 127;
  268.     shr(mant, 8);
  269.     round(mant, 2);
  270.     if (mant[0] & 0x100)       /* did we scale up by one? */
  271. shr(mant, 1), exponent++;
  272.     mant[0] &= 0x7F;        /* remove leading one */
  273.     put(result+2,(exponent << 7) | mant[0] | sign);
  274.     put(result+0,mant[1]);
  275. } else if (exponent < -126 && exponent >= -149) {
  276.     /*
  277.      * Denormal.
  278.      */
  279.     int shift = -(exponent+118);
  280.     int sh = shift % 16, wds = shift / 16;
  281.     shr(mant, sh);
  282.     if (round(mant, 2-wds) || (sh>0 && (mant[0]&(0x8000>>(sh-1))))) {
  283. shr(mant, 1);
  284. if (sh==0)
  285.     mant[0] |= 0x8000;
  286. exponent++;
  287.     }
  288.     put(result+2,(wds == 0 ? mant[0] : 0) | sign);
  289.     put(result+0,(wds <= 1 ? mant[1-wds] : 0));
  290. } else {
  291.     if (exponent > 0) {
  292. error(ERR_NONFATAL, "overflow in floating-point constant");
  293. return 0;
  294.     } else
  295. memset (result, 0, 4);
  296. }
  297.     } else {
  298. memset (result, 0, 4);
  299.     }
  300.     return 1;
  301. }
  302. static int to_ldoub(char *str, long sign, unsigned char *result,
  303.     efunc error) 
  304. {
  305.     unsigned short mant[MANT_WORDS];
  306.     long exponent;
  307.     sign = (sign < 0 ? 0x8000L : 0L);
  308.     flconvert (str, mant, &exponent, error);
  309.     if (mant[0] & 0x8000) {
  310. /*
  311.  * Non-zero.
  312.  */
  313. exponent--;
  314. if (exponent >= -16383 && exponent <= 16384) {
  315.     /*
  316.      * Normalised.
  317.      */
  318.     exponent += 16383;
  319.     if (round(mant, 4))        /* did we scale up by one? */
  320. shr(mant, 1), mant[0] |= 0x8000, exponent++;
  321.     put(result+8,exponent | sign);
  322.     put(result+6,mant[0]);
  323.     put(result+4,mant[1]);
  324.     put(result+2,mant[2]);
  325.     put(result+0,mant[3]);
  326. } else if (exponent < -16383 && exponent >= -16446) {
  327.     /*
  328.      * Denormal.
  329.      */
  330.     int shift = -(exponent+16383);
  331.     int sh = shift % 16, wds = shift / 16;
  332.     shr(mant, sh);
  333.     if (round(mant, 4-wds) || (sh>0 && (mant[0]&(0x8000>>(sh-1))))) {
  334. shr(mant, 1);
  335. if (sh==0)
  336.     mant[0] |= 0x8000;
  337. exponent++;
  338.     }
  339.     put(result+8,sign);
  340.     put(result+6,(wds == 0 ? mant[0] : 0));
  341.     put(result+4,(wds <= 1 ? mant[1-wds] : 0));
  342.     put(result+2,(wds <= 2 ? mant[2-wds] : 0));
  343.     put(result+0,(wds <= 3 ? mant[3-wds] : 0));
  344. } else {
  345.     if (exponent > 0) {
  346. error(ERR_NONFATAL, "overflow in floating-point constant");
  347. return 0;
  348.     } else
  349. memset (result, 0, 10);
  350. }
  351.     } else {
  352. /*
  353.  * Zero.
  354.  */
  355. memset (result, 0, 10);
  356.     }
  357.     return 1;
  358. }
  359. int float_const (char *number, long sign, unsigned char *result, int bytes,
  360.  efunc error) 
  361. {
  362.     if (bytes == 4)
  363. return to_float (number, sign, result, error);
  364.     else if (bytes == 8)
  365. return to_double (number, sign, result, error);
  366.     else if (bytes == 10)
  367. return to_ldoub (number, sign, result, error);
  368.     else {
  369. error(ERR_PANIC, "strange value %d passed to float_const", bytes);
  370. return 0;
  371.     }
  372. }