mirror of
https://github.com/netwide-assembler/nasm.git
synced 2025-07-24 10:25:42 -04:00
Support binary and octal floating-point
For consistency, support binary and octal floating-point, and accept a "0d" or "0t" prefix for decimal floating-point. However, we do not accept a binary exponent (p) for a decimal mantissa, or vice versa.
This commit is contained in:
parent
bea0bbb62c
commit
c65a2f634b
78
float.c
78
float.c
@ -424,29 +424,33 @@ static bool ieee_round(int sign, uint16_t * mant, int32_t i)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hexval(char c)
|
/* Returns a value >= 16 if not a valid hex digit */
|
||||||
|
static unsigned int hexval(char c)
|
||||||
{
|
{
|
||||||
if (c >= '0' && c <= '9')
|
unsigned int v = (unsigned char) c;
|
||||||
return c - '0';
|
|
||||||
else if (c >= 'a' && c <= 'f')
|
if (v >= '0' && v <= '9')
|
||||||
return c - 'a' + 10;
|
return v - '0';
|
||||||
else
|
else
|
||||||
return c - 'A' + 10;
|
return (v|0x20) - 'a' + 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ieee_flconvert_hex(const char *string, uint16_t * mant,
|
/* Handle floating-point numbers with radix 2^bits and binary exponent */
|
||||||
int32_t * exponent)
|
static bool ieee_flconvert_bin(const char *string, int bits,
|
||||||
|
uint16_t * mant, int32_t * exponent)
|
||||||
{
|
{
|
||||||
static const int log2tbl[16] =
|
static const int log2tbl[16] =
|
||||||
{ -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 };
|
{ -1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3 };
|
||||||
uint16_t mult[MANT_WORDS + 1], *mp;
|
uint16_t mult[MANT_WORDS + 1], *mp;
|
||||||
int ms;
|
int ms;
|
||||||
int32_t twopwr;
|
int32_t twopwr;
|
||||||
int seendot, seendigit;
|
bool seendot, seendigit;
|
||||||
unsigned char c;
|
unsigned char c;
|
||||||
|
int radix = 1 << bits;
|
||||||
|
unsigned int v;
|
||||||
|
|
||||||
twopwr = 0;
|
twopwr = 0;
|
||||||
seendot = seendigit = 0;
|
seendot = seendigit = false;
|
||||||
ms = 0;
|
ms = 0;
|
||||||
mp = NULL;
|
mp = NULL;
|
||||||
|
|
||||||
@ -461,17 +465,15 @@ static bool ieee_flconvert_hex(const char *string, uint16_t * mant,
|
|||||||
"too many periods in floating-point constant");
|
"too many periods in floating-point constant");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (isxdigit(c)) {
|
} else if ((v = hexval(c)) < (unsigned int)radix) {
|
||||||
int v = hexval(c);
|
|
||||||
|
|
||||||
if (!seendigit && v) {
|
if (!seendigit && v) {
|
||||||
int l = log2tbl[v];
|
int l = log2tbl[v];
|
||||||
|
|
||||||
seendigit = 1;
|
seendigit = 1;
|
||||||
mp = mult;
|
mp = mult;
|
||||||
ms = 15 - l;
|
ms = 15-l;
|
||||||
|
|
||||||
twopwr = seendot ? twopwr - 4 + l : l - 3;
|
twopwr = seendot ? twopwr-bits+l : l+1-bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (seendigit) {
|
if (seendigit) {
|
||||||
@ -483,13 +485,13 @@ static bool ieee_flconvert_hex(const char *string, uint16_t * mant,
|
|||||||
ms += 16;
|
ms += 16;
|
||||||
}
|
}
|
||||||
*mp |= v << ms;
|
*mp |= v << ms;
|
||||||
ms -= 4;
|
ms -= bits;
|
||||||
|
|
||||||
if (!seendot)
|
if (!seendot)
|
||||||
twopwr += 4;
|
twopwr += bits;
|
||||||
} else {
|
} else {
|
||||||
if (seendot)
|
if (seendot)
|
||||||
twopwr -= 4;
|
twopwr -= bits;
|
||||||
}
|
}
|
||||||
} else if (c == 'p' || c == 'P') {
|
} else if (c == 'p' || c == 'P') {
|
||||||
int32_t e;
|
int32_t e;
|
||||||
@ -656,13 +658,41 @@ static int to_float(const char *str, int sign, uint8_t * result,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (str[0] == '0' &&
|
if (str[0] == '0') {
|
||||||
(str[1] == 'x' || str[1] == 'X' || str[1] == 'h' || str[1] == 'H'))
|
switch (str[1]) {
|
||||||
ok = ieee_flconvert_hex(str + 2, mant, &exponent);
|
case 'x': case 'X':
|
||||||
else if (str[0] == '$')
|
case 'h': case 'H':
|
||||||
ok = ieee_flconvert_hex(str + 1, mant, &exponent);
|
ok = ieee_flconvert_bin(str+2, 4, mant, &exponent);
|
||||||
else
|
break;
|
||||||
|
case 'o': case 'O':
|
||||||
|
case 'q': case 'Q':
|
||||||
|
ok = ieee_flconvert_bin(str+2, 3, mant, &exponent);
|
||||||
|
break;
|
||||||
|
case 'b': case 'B':
|
||||||
|
case 'y': case 'Y':
|
||||||
|
ok = ieee_flconvert_bin(str+2, 1, mant, &exponent);
|
||||||
|
break;
|
||||||
|
case 'd': case 'D':
|
||||||
|
case 't': case 'T':
|
||||||
|
ok = ieee_flconvert(str+2, mant, &exponent);
|
||||||
|
break;
|
||||||
|
case '0': case '1': case '2': case '3': case '4':
|
||||||
|
case '5': case '6': case '7': case '8': case '9':
|
||||||
|
case '\0':
|
||||||
|
/* Leading zero was just a zero */
|
||||||
|
ok = ieee_flconvert(str, mant, &exponent);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
error(ERR_NONFATAL,
|
||||||
|
"floating-point constant: invalid radix `%c'", str[1]);
|
||||||
|
ok = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (str[0] == '$') {
|
||||||
|
ok = ieee_flconvert_bin(str+1, 4, mant, &exponent);
|
||||||
|
} else {
|
||||||
ok = ieee_flconvert(str, mant, &exponent);
|
ok = ieee_flconvert(str, mant, &exponent);
|
||||||
|
}
|
||||||
|
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
type = FL_QNAN;
|
type = FL_QNAN;
|
||||||
|
@ -141,7 +141,7 @@ int stdscan(void *private_data, struct tokenval *tv)
|
|||||||
}
|
}
|
||||||
} else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
|
} else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
|
||||||
is_hex = true;
|
is_hex = true;
|
||||||
} else if (is_hex && (c == 'P' || c == 'p')) {
|
} else if (c == 'P' || c == 'p') {
|
||||||
is_float = true;
|
is_float = true;
|
||||||
if (*stdscan_bufptr == '+' || *stdscan_bufptr == '-')
|
if (*stdscan_bufptr == '+' || *stdscan_bufptr == '-')
|
||||||
stdscan_bufptr++;
|
stdscan_bufptr++;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
;; Integer constants...
|
||||||
|
|
||||||
dd 1010_0101 ; Decimal
|
dd 1010_0101 ; Decimal
|
||||||
dd 01010_0101 ; Decimal (*not* octal!)
|
dd 01010_0101 ; Decimal (*not* octal!)
|
||||||
dd 0d1010_0101 ; Decimal
|
dd 0d1010_0101 ; Decimal
|
||||||
@ -20,4 +22,19 @@
|
|||||||
dd 1010_0101h ; Hex
|
dd 1010_0101h ; Hex
|
||||||
dd 1010_0101x ; Hex
|
dd 1010_0101x ; Hex
|
||||||
dd $1010_0101 ; Hex
|
dd $1010_0101 ; Hex
|
||||||
|
|
||||||
|
;; Floating-point constants
|
||||||
|
;; All of these should output B4A21147
|
||||||
|
dd 3.7282705e+4 ; Decimal
|
||||||
|
dd 00003.7282705e+4 ; Decimal
|
||||||
|
dd 0d3.7282705e+4 ; Decimal
|
||||||
|
dd 0t3.7282705e+4 ; Decimal
|
||||||
|
|
||||||
|
dd 0x1.23456789p+15 ; Hex
|
||||||
|
dd 0h1.23456789p+15 ; Hex
|
||||||
|
|
||||||
|
dd 0o1.10642547422p+15 ; Octal
|
||||||
|
dd 0q1.10642547422p+15 ; Octal
|
||||||
|
|
||||||
|
dd 0b1.0010_0011_0100_0101_0110_0111_1000_1001p+15 ; Binary
|
||||||
|
dd 0y1.0010_0011_0100_0101_0110_0111_1000_1001p+15 ; Binary
|
||||||
|
Loading…
x
Reference in New Issue
Block a user