From: H. Peter Anvin Date: Wed, 19 Sep 2007 01:31:26 +0000 (-0700) Subject: Support C99-style hexadecimal floating point. X-Git-Tag: nasm-2.11.05~1956^2~4^2~7 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fe2177fe4287bbfa9205bcd362694f47870a3c30;p=platform%2Fupstream%2Fnasm.git Support C99-style hexadecimal floating point. Add support for C99-style hexadecimal floating point. The format is 0x p . 0x1.0e+1 thus is the same as 2.0. --- diff --git a/float.c b/float.c index a6ad393..08dfdb4 100644 --- a/float.c +++ b/float.c @@ -8,6 +8,7 @@ * initial version 13/ix/96 by Simon Tatham */ +#include #include #include #include @@ -56,6 +57,91 @@ static int ieee_multiply(uint16_t *to, uint16_t *from) } } +static int hexval(char c) +{ + if (c >= '0' && c <= '9') + return c-'0'; + else if (c >= 'a' && c <= 'f') + return c-'a'+10; + else + return c-'A'+10; +} + +static void ieee_flconvert_hex(char *string, uint16_t *mant, + int32_t *exponent, efunc error) +{ + static const int log2tbl[16] = + { -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 }; + uint16_t mult[MANT_WORDS+1], *mp; + int ms; + int32_t twopwr; + int seendot, seendigit; + unsigned char c; + + twopwr = 0; + seendot = seendigit = 0; + + memset(mult, 0, sizeof mult); + + while ((c = *string++) != '\0') { + if (c == '.') { + if (!seendot) + seendot = TRUE; + else { + error(ERR_NONFATAL, + "too many periods in floating-point constant"); + return; + } + } else if (isxdigit(c)) { + int v = hexval(c); + + if (!seendigit && v) { + int l = log2tbl[v]; + + seendigit = 1; + mp = mult; + ms = 15-l; + + twopwr = seendot ? twopwr-4+l : l-3; + } + + if (seendigit) { + if (ms <= 0) { + *mp |= v >> -ms; + mp++; + if (mp > &mult[MANT_WORDS]) + mp = &mult[MANT_WORDS]; /* Guard slot */ + ms += 16; + } + *mp |= v << ms; + ms -= 4; + + if (!seendot) + twopwr += 4; + } else { + if (seendot) + twopwr -= 4; + } + } else if (c == 'p' || c == 'P') { + twopwr += atoi(string); + break; + } else { + error(ERR_NONFATAL, + "floating-point constant: `%c' is invalid character", + *string); + return; + } + } + + if (!seendigit) { + memset(mant, 0, 2*MANT_WORDS); /* Zero */ + *exponent = 0; + } else { + memcpy(mant, mult, 2*MANT_WORDS); + *exponent = twopwr; + } +} + static void ieee_flconvert(char *string, uint16_t *mant, int32_t *exponent, efunc error) { @@ -66,6 +152,11 @@ static void ieee_flconvert(char *string, uint16_t *mant, int32_t tenpwr, twopwr; int extratwos, started, seendot; + if (string[0] == '0' && (string[1] == 'x' || string[1] == 'X')) { + ieee_flconvert_hex(string+2, mant, exponent, error); + return; + } + p = digits; tenpwr = 0; started = seendot = FALSE; diff --git a/stdscan.c b/stdscan.c index d4ad696..b6a4ee8 100644 --- a/stdscan.c +++ b/stdscan.c @@ -130,7 +130,9 @@ int stdscan(void *private_data, struct tokenval *tv) stdscan_bufptr++; while (isnumchar(*stdscan_bufptr) || ((stdscan_bufptr[-1] == 'e' - || stdscan_bufptr[-1] == 'E') + || stdscan_bufptr[-1] == 'E' + || stdscan_bufptr[-1] == 'p' + || stdscan_bufptr[-1] == 'P') && (*stdscan_bufptr == '-' || *stdscan_bufptr == '+'))) { stdscan_bufptr++; }