summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@zytor.com>2007-10-22 16:53:48 -0700
committerH. Peter Anvin <hpa@zytor.com>2007-10-22 16:53:48 -0700
commitbea0bbb62c9947421bc0fddcd2b58a40435e2181 (patch)
tree21623213cc08b04a9eb771b2a46bb1e057a1948c
parent3b2ad1bc370653e90d6b2fa9cfc587a7aea405f3 (diff)
downloadnasm-bea0bbb62c9947421bc0fddcd2b58a40435e2181.tar.gz
More consistent handling of radix letters
Allow any radix letter from the set [bydtoqhx] to be used either "Intel-style" (0...x) or "C-style" (0x...). In Intel style, the leading 0 remains optional as long as the first digit is in the range 0-9. As a consequence, allow the prefix "0h" for hexadecimal floating point.
-rw-r--r--float.c3
-rw-r--r--nasmlib.c46
-rw-r--r--stdscan.c15
-rw-r--r--test/floatx.asm171
-rw-r--r--test/radix.asm23
5 files changed, 235 insertions, 23 deletions
diff --git a/float.c b/float.c
index 843dbdfa..a2df323d 100644
--- a/float.c
+++ b/float.c
@@ -656,7 +656,8 @@ static int to_float(const char *str, int sign, uint8_t * result,
break;
}
} else {
- if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X'))
+ if (str[0] == '0' &&
+ (str[1] == 'x' || str[1] == 'X' || str[1] == 'h' || str[1] == 'H'))
ok = ieee_flconvert_hex(str + 2, mant, &exponent);
else if (str[0] == '$')
ok = ieee_flconvert_hex(str + 1, mant, &exponent);
diff --git a/nasmlib.c b/nasmlib.c
index 5e43daab..e368a929 100644
--- a/nasmlib.c
+++ b/nasmlib.c
@@ -196,6 +196,26 @@ char *nasm_strsep(char **stringp, const char *delim)
#define lib_isnumchar(c) (isalnum(c) || (c) == '$' || (c) == '_')
#define numvalue(c) ((c)>='a' ? (c)-'a'+10 : (c)>='A' ? (c)-'A'+10 : (c)-'0')
+static int radix_letter(char c)
+{
+ switch (c) {
+ case 'b': case 'B':
+ case 'y': case 'Y':
+ return 2; /* Binary */
+ case 'o': case 'O':
+ case 'q': case 'Q':
+ return 8; /* Octal */
+ case 'h': case 'H':
+ case 'x': case 'X':
+ return 16; /* Hexadecimal */
+ case 'd': case 'D':
+ case 't': case 'T':
+ return 10; /* Decimal */
+ default:
+ return 0; /* Not a known radix letter */
+ }
+}
+
int64_t readnum(char *str, bool *error)
{
char *r = str, *q;
@@ -225,24 +245,20 @@ int64_t readnum(char *str, bool *error)
q++; /* find end of number */
/*
- * If it begins 0x, 0X or $, or ends in H, it's in hex. if it
- * ends in Q, it's octal. if it ends in B, it's binary.
- * Otherwise, it's ordinary decimal.
+ * Handle radix formats:
+ *
+ * 0<radix-letter><string>
+ * $<string> (hexadecimal)
+ * <string><radix-letter>
*/
- if (*r == '0' && (r[1] == 'x' || r[1] == 'X'))
- radix = 16, r += 2;
+ if (*r == '0' && (radix = radix_letter(r[1])))
+ r += 2;
else if (*r == '$')
- radix = 16, r++;
- else if (q[-1] == 'H' || q[-1] == 'h')
- radix = 16, q--;
- else if (q[-1] == 'Q' || q[-1] == 'q' || q[-1] == 'O' || q[-1] == 'o')
- radix = 8, q--;
- else if (q[-1] == 'B' || q[-1] == 'b' || q[-1] == 'Y' || q[-1] == 'y')
- radix = 2, q--;
- else if (q[-1] == 'D' || q[-1] == 'd' || q[-1] == 'T' || q[-1] == 't')
- radix = 10, q--;
+ radix = 16, r++;
+ else if ((radix = radix_letter(q[-1])) != 0)
+ q--;
else
- radix = 10;
+ radix = 10;
/*
* If this number has been found for us by something other than
diff --git a/stdscan.c b/stdscan.c
index 9235b08f..dda4e0a3 100644
--- a/stdscan.c
+++ b/stdscan.c
@@ -119,13 +119,14 @@ int stdscan(void *private_data, struct tokenval *tv)
bool is_hex = false;
bool is_float = false;
bool has_e = false;
- bool has_h = false;
char c;
- r = stdscan_bufptr++;
+ r = stdscan_bufptr;
- if (r[0] == '$' || (r[0] == '0' || (r[1] == 'x' || r[1] == 'X')))
+ if (*stdscan_bufptr == '$') {
+ stdscan_bufptr++;
is_hex = true;
+ }
for (;;) {
c = *stdscan_bufptr++;
@@ -138,9 +139,9 @@ int stdscan(void *private_data, struct tokenval *tv)
is_float = true;
stdscan_bufptr++;
}
- } else if (c == 'H' || c == 'h') {
- has_h = true;
- } else if (is_hex & (c == 'P' || c == 'p')) {
+ } else if (c == 'H' || c == 'h' || c == 'X' || c == 'x') {
+ is_hex = true;
+ } else if (is_hex && (c == 'P' || c == 'p')) {
is_float = true;
if (*stdscan_bufptr == '+' || *stdscan_bufptr == '-')
stdscan_bufptr++;
@@ -153,7 +154,7 @@ int stdscan(void *private_data, struct tokenval *tv)
}
stdscan_bufptr--; /* Point to first character beyond number */
- if (has_e && !has_h) {
+ if (has_e && !is_hex) {
/* 1e13 is floating-point, but 1e13h is not */
is_float = true;
}
diff --git a/test/floatx.asm b/test/floatx.asm
index 22841e6b..127f3535 100644
--- a/test/floatx.asm
+++ b/test/floatx.asm
@@ -179,6 +179,177 @@
; 16-bit
dw 1.0
+ dw 0h1.0
+ dw 2.0
+ dw 0h2.0
+ dw 0h1.0p+1
+ dw 0h1.0p-1
+ dw 0h0.0
+ dw 0h1.23456789
+ dw 0h0.123456789
+ dw 0h0.0000123456789
+ dw 0h1.23456789p10
+ dw 0h1.23456789p+10
+ dw 0h1.23456789p-10
+ dw 0h0.123456789p10
+ dw 0h0.123456789p+10
+ dw 0h0.123456789abcdef0123456789abcdef012345p-10
+ dw 0h0.0000123456789
+ dw 0h0.0000123456789p+10
+ dw 0h0.0000123456789p-10
+ dw 0h1.0p-25 ; Underflow
+ dw 0h1.0p-24 ; Smallest denorm
+ dw 0h1.ffffffffffffffffffffffffffffp-16 ; Rounds to denorm
+ dw 0h1.0p-15 ; Denorm
+ dw 0h1.ffffffffffffffffffffffffffffp-15 ; Rounds to normal
+ dw 0h1.0p-14 ; Smallest non-denorm
+ dw 0h1.0p+15 ; Biggest possible exponent
+ dw 0h1.ffffffffffffffffffffffffffffp+15 ; Rounds to infinity
+ dw Inf ; Infinity
+ dw NaN
+
+; 32-bit
+ dd 1.0
+ dd 0h1.0
+ dd 2.0
+ dd 0h2.0
+ dd 0h1.0p+1
+ dd 0h1.0p-1
+ dd 0h0.0
+ dd 0h1.23456789
+ dd 0h0.123456789
+ dd 0h0.0000123456789
+ dd 0h1.23456789p10
+ dd 0h1.23456789p+10
+ dd 0h1.23456789p-10
+ dd 0h0.123456789p10
+ dd 0h0.123456789p+10
+ dd 0h0.123456789abcdef0123456789abcdef012345p-10
+ dd 0h0.0000123456789
+ dd 0h0.0000123456789p+10
+ dd 0h0.0000123456789p-10
+ dd 0h123456789.0
+ dd 0h0000123456789.0
+ dd 0h123456789.0p+0
+ dd 0h123456789.0p+64
+ dd 0h1.0p-150 ; Underflow
+ dd 0h1.0p-149 ; Smallest denorm
+ dd 0h1.ffffffffffffffffffffffffffffp-128 ; Rounds to denorm
+ dd 0h1.0p-127 ; Denorm
+ dd 0h1.ffffffffffffffffffffffffffffp-127 ; Rounds to normal
+ dd 0h1.0p-126 ; Smallest non-denorm
+ dd 0h1.0p+127 ; Biggest possible exponent
+ dd 0h1.ffffffffffffffffffffffffffffp+127 ; Rounds to infinity
+ dd Inf ; Infinity
+ dd NaN
+
+; 64-bit
+ dq 1.0
+ dq 0h1.0
+ dq 2.0
+ dq 0h2.0
+ dq 0h1.0p+1
+ dq 0h1.0p-1
+ dq 0h0.0
+ dq 0h1.23456789
+ dq 0h0.123456789
+ dq 0h0.0000123456789
+ dq 0h1.23456789p10
+ dq 0h1.23456789p+10
+ dq 0h1.23456789p-10
+ dq 0h0.123456789p10
+ dq 0h0.123456789p+10
+ dq 0h0.123456789abcdef0123456789abcdef012345p-10
+ dq 0h0.0000123456789
+ dq 0h0.0000123456789p+10
+ dq 0h0.0000123456789p-10
+ dq 0h123456789.0
+ dq 0h0000123456789.0
+ dq 0h123456789.0p+0
+ dq 0h123456789.0p+300
+ dq 0h1.0p-1075 ; Underflow
+ dq 0h1.0p-1074 ; Smallest denorm
+ dq 0h1.ffffffffffffffffffffffffffffp-1024 ; Rounds to denorm
+ dq 0h1.0p-1023 ; Denorm
+ dq 0h1.ffffffffffffffffffffffffffffp-1023 ; Rounds to normal
+ dq 0h1.0p-1022 ; Smallest non-denorm
+ dq 0h1.0p+1023 ; Biggest possible exponent
+ dq 0h1.ffffffffffffffffffffffffffffp+1023 ; Rounds to infinity
+ dq Inf ; Infinity
+ dq NaN
+
+; 80-bit
+ dt 1.0
+ dt 0h1.0
+ dt 2.0
+ dt 0h2.0
+ dt 0h1.0p+1
+ dt 0h1.0p-1
+ dt 0h0.0
+ dt 0h1.23456789
+ dt 0h0.123456789
+ dt 0h0.0000123456789
+ dt 0h1.23456789p10
+ dt 0h1.23456789p+10
+ dt 0h1.23456789p-10
+ dt 0h0.123456789p10
+ dt 0h0.123456789p+10
+ dt 0h0.123456789abcdef0123456789abcdef012345p-10
+ dt 0h0.0000123456789
+ dt 0h0.0000123456789p+10
+ dt 0h0.0000123456789p-10
+ dt 0h123456789.0
+ dt 0h0000123456789.0
+ dt 0h123456789.0p+0
+ dt 0h123456789.0p+1024
+ dt 0h1.0p-16446 ; Underflow
+ dt 0h1.0p-16445 ; Smallest denorm
+ dt 0h1.ffffffffffffffffffffffffffffp-16384 ; Rounds to denorm
+ dt 0h1.0p-16383 ; Denorm
+ dt 0h1.ffffffffffffffffffffffffffffp-16383 ; Rounds to normal
+ dt 0h1.0p-16382 ; Smallest non-denorm
+ dt 0h1.0p+16383 ; Biggest possible exponent
+ dt 0h1.ffffffffffffffffffffffffffffp+16383 ; Rounds to infinity
+ dt Inf ; Infinity
+ dt NaN
+
+; 128-bit
+ do 1.0
+ do 0h1.0
+ do 2.0
+ do 0h2.0
+ do 0h1.0p+1
+ do 0h1.0p-1
+ do 0h0.0
+ do 0h1.23456789
+ do 0h0.123456789
+ do 0h0.0000123456789
+ do 0h1.23456789p10
+ do 0h1.23456789p+10
+ do 0h1.23456789p-10
+ do 0h0.123456789p10
+ do 0h0.123456789p+10
+ do 0h0.123456789abcdef0123456789abcdef012345p-10
+ do 0h0.0000123456789
+ do 0h0.0000123456789p+10
+ do 0h0.0000123456789p-10
+ do 0h123456789.0
+ do 0h0000123456789.0
+ do 0h123456789.0p+0
+ do 0h123456789.0p+1024
+ do 0h1.0p-16495 ; Underflow
+ do 0h1.0p-16494 ; Smallest denorm
+ do 0h1.ffffffffffffffffffffffffffffffffp-16384 ; Rounds to denorm
+ do 0h1.0p-16383 ; Denorm
+ do 0h1.ffffffffffffffffffffffffffffffffp-16383 ; Rounds to normal
+ do 0h1.0p-16382 ; Smallest non-denorm
+ do 0h1.0p+16383 ; Biggest possible exponent
+ do 0h1.ffffffffffffffffffffffffffffffffp+16383 ; Rounds to infinity
+ do Inf ; Infinity
+ do NaN
+
+; 16-bit
+ dw 1.0
dw $1.0
dw 2.0
dw $2.0
diff --git a/test/radix.asm b/test/radix.asm
new file mode 100644
index 00000000..35dbceef
--- /dev/null
+++ b/test/radix.asm
@@ -0,0 +1,23 @@
+ dd 1010_0101 ; Decimal
+ dd 01010_0101 ; Decimal (*not* octal!)
+ dd 0d1010_0101 ; Decimal
+ dd 0t1010_0101 ; Decimal
+ dd 1010_0101d ; Decimal
+ dd 1010_0101t ; Decimal
+
+ dd 0b1010_0101 ; Binary
+ dd 0y1010_0101 ; Binary
+ dd 1010_0101b ; Binary
+ dd 1010_0101y ; Binary
+
+ dd 0o1010_0101 ; Octal
+ dd 0q1010_0101 ; Octal
+ dd 1010_0101o ; Octal
+ dd 1010_0101q ; Octal
+
+ dd 0h1010_0101 ; Hex
+ dd 0x1010_0101 ; Hex
+ dd 1010_0101h ; Hex
+ dd 1010_0101x ; Hex
+ dd $1010_0101 ; Hex
+ \ No newline at end of file