From f0dec3f488c12352f62aa8c3ef3adc22599cb1cb Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Wed, 11 Aug 2021 08:36:28 +0200 Subject: [PATCH] gas: support NaN flavors Like for infinity, there isn't just a single NaN. The sign bit may be of interest and, going beyond infinity, whether the value is quiet or signalling may be even more relevant to be able to encode. Note that an anomaly with x86'es double extended precision NaN values gets taken care of at the same time: For all other formats a positive value with all mantissa bits set was used, while here a negative value with all non-significant mantissa bits clear was chose for an unknown reason. For m68k, since I don't know their X_PRECISION floating point value layout, a warning gets issued if any of the new flavors was attempted to be encoded that way. However likely it may be that, given that the code lives in a source file supposedly implementing IEEE-compliant formats, the bit patterns of the individual words match x86'es, I didn't want to guess so. And my very, very old paper doc doesn't even mention floating point formats other than single and double. --- gas/atof-generic.c | 20 +++++++- gas/config/atof-ieee.c | 47 +++++++++++------ gas/config/tc-tic4x.c | 4 +- gas/flonum.h | 4 ++ gas/testsuite/gas/all/float.s | 8 +++ gas/testsuite/gas/i386/fp-elf32.d | 24 +++++++++ gas/testsuite/gas/i386/fp-elf64.d | 24 +++++++++ gas/testsuite/gas/i386/fp.d | 24 +++++++++ gas/testsuite/gas/i386/fp.s | 84 +++++++++++++++++++++++++++++++ 9 files changed, 221 insertions(+), 18 deletions(-) diff --git a/gas/atof-generic.c b/gas/atof-generic.c index 91d8aba4814..e93353419e9 100644 --- a/gas/atof-generic.c +++ b/gas/atof-generic.c @@ -113,11 +113,29 @@ atof_generic (/* return pointer to just AFTER number we read. */ switch (first_digit[0]) { + case 's': + case 'S': + case 'q': + case 'Q': + if (!strncasecmp ("nan", first_digit + 1, 3)) + { + address_of_generic_floating_point_number->sign = + digits_sign_char == '+' ? TOUPPER (first_digit[0]) + : TOLOWER (first_digit[0]); + address_of_generic_floating_point_number->exponent = 0; + address_of_generic_floating_point_number->leader = + address_of_generic_floating_point_number->low; + *address_of_string_pointer = first_digit + 4; + return 0; + } + break; + case 'n': case 'N': if (!strncasecmp ("nan", first_digit, 3)) { - address_of_generic_floating_point_number->sign = 0; + address_of_generic_floating_point_number->sign = + digits_sign_char == '+' ? 0 : 'q'; address_of_generic_floating_point_number->exponent = 0; address_of_generic_floating_point_number->leader = address_of_generic_floating_point_number->low; diff --git a/gas/config/atof-ieee.c b/gas/config/atof-ieee.c index 7f95d05d8b0..9cf6aced4ab 100644 --- a/gas/config/atof-ieee.c +++ b/gas/config/atof-ieee.c @@ -19,6 +19,7 @@ 02110-1301, USA. */ #include "as.h" +#include "safe-ctype.h" /* Flonums returned here. */ extern FLONUM_TYPE generic_floating_point_number; @@ -324,24 +325,34 @@ gen_to_words (LITTLENUM_TYPE *words, int precision, long exponent_bits) return return_value; } - /* NaN: Do the right thing. */ - if (generic_floating_point_number.sign == 0) + switch (generic_floating_point_number.sign) { + /* NaN: Do the right thing. */ + case 0: + case 'Q': case 'q': + case 'S': case 's': if (TC_LARGEST_EXPONENT_IS_NORMAL (precision)) as_warn (_("NaNs are not supported by this target")); if (precision == H_PRECISION) { - words[0] = 0x7fff; + if (TOUPPER (generic_floating_point_number.sign) != 'S') + words[0] = 0x7fff; + else + words[0] = exponent_bits == 5 ? 0x7dff : 0x7fbf; } else if (precision == F_PRECISION) { - words[0] = 0x7fff; + words[0] = TOUPPER (generic_floating_point_number.sign) == 'S' + ? 0x7fbf : 0x7fff; words[1] = 0xffff; } else if (precision == X_PRECISION) { #ifdef TC_M68K + if (generic_floating_point_number.sign) + as_warn (_("NaN flavors are not supported by this target")); + words[0] = 0x7fff; words[1] = 0; words[2] = 0xffff; @@ -350,11 +361,12 @@ gen_to_words (LITTLENUM_TYPE *words, int precision, long exponent_bits) words[5] = 0xffff; #else /* ! TC_M68K */ #ifdef TC_I386 - words[0] = 0xffff; - words[1] = 0xc000; - words[2] = 0; - words[3] = 0; - words[4] = 0; + words[0] = 0x7fff; + words[1] = TOUPPER (generic_floating_point_number.sign) == 'S' + ? 0xbfff : 0xffff; + words[2] = 0xffff; + words[3] = 0xffff; + words[4] = 0xffff; #else /* ! TC_I386 */ abort (); #endif /* ! TC_I386 */ @@ -362,15 +374,19 @@ gen_to_words (LITTLENUM_TYPE *words, int precision, long exponent_bits) } else { - words[0] = 0x7fff; + words[0] = TOUPPER (generic_floating_point_number.sign) == 'S' + ? 0x7ff7 : 0x7fff; words[1] = 0xffff; words[2] = 0xffff; words[3] = 0xffff; } + + if (ISLOWER (generic_floating_point_number.sign)) + words[0] |= 0x8000; + return return_value; - } - else if (generic_floating_point_number.sign == 'P') - { + + case 'P': if (TC_LARGEST_EXPONENT_IS_NORMAL (precision)) as_warn (_("Infinities are not supported by this target")); @@ -413,9 +429,8 @@ gen_to_words (LITTLENUM_TYPE *words, int precision, long exponent_bits) words[3] = 0; } return return_value; - } - else if (generic_floating_point_number.sign == 'N') - { + + case 'N': if (TC_LARGEST_EXPONENT_IS_NORMAL (precision)) as_warn (_("Infinities are not supported by this target")); diff --git a/gas/config/tc-tic4x.c b/gas/config/tc-tic4x.c index c456dffbbad..c00121c30ba 100644 --- a/gas/config/tc-tic4x.c +++ b/gas/config/tc-tic4x.c @@ -384,8 +384,10 @@ tic4x_gen_to_words (FLONUM_TYPE flonum, LITTLENUM_TYPE *words, int precision) /* 0.0e0 or NaN seen. */ if (flonum.low > flonum.leader /* = 0.0e0 */ || flonum.sign == 0) /* = NaN */ + || flonum.sign == 'Q' || flonum.sign == 'q' /* = QNaN */ + || flonum.sign == 'S' || flonum.sign == 's' /* = SNaN */ { - if(flonum.sign == 0) + if (flonum.sign != '+' && flonum.sign != '-') as_bad (_("Nan, using zero.")); words[0] = 0x8000; return return_value; diff --git a/gas/flonum.h b/gas/flonum.h index 1bb638b2f91..59d582d570e 100644 --- a/gas/flonum.h +++ b/gas/flonum.h @@ -47,6 +47,10 @@ /* JF: A sign value of 0 means we have been asked to assemble NaN A sign value of 'P' means we've been asked to assemble +Inf A sign value of 'N' means we've been asked to assemble -Inf + A sign value of 'Q' means we've been asked to assemble +QNaN + A sign value of 'q' means we've been asked to assemble -QNaN + A sign value of 'S' means we've been asked to assemble +SNaN + A sign value of 's' means we've been asked to assemble -SNaN */ struct FLONUM_STRUCT { LITTLENUM_TYPE *low; /* low order littlenum of a bignum */ diff --git a/gas/testsuite/gas/all/float.s b/gas/testsuite/gas/all/float.s index eabb24c3738..f401ed31a84 100644 --- a/gas/testsuite/gas/all/float.s +++ b/gas/testsuite/gas/all/float.s @@ -7,6 +7,10 @@ foo: .single 0r1.2345e+06 .dc.s 1 .dc.s 0f:1234 + .dc.s Inf + .dc.s NaN + .dc.s QNaN + .dc.s SNaN .dcb.s 1 .dcb.s 1, 1 .dcb.s 1, 0s:4321 @@ -14,6 +18,10 @@ foo: .single 0r1.2345e+06 .dc.d 1 .dc.d 0d:1234 + .dc.d +Inf + .dc.d -NaN + .dc.d +QNaN + .dc.d -SNaN .dcb.d 1 .dcb.d 1, 1 .dcb.d 1, 0r:4321 diff --git a/gas/testsuite/gas/i386/fp-elf32.d b/gas/testsuite/gas/i386/fp-elf32.d index 798cb6b8382..ac67c2ae721 100644 --- a/gas/testsuite/gas/i386/fp-elf32.d +++ b/gas/testsuite/gas/i386/fp-elf32.d @@ -15,3 +15,27 @@ Contents of section .data: 0070 00000080 fdbf0000 00000000 00000080 .* 0080 ff030000 aaaaaaaa aaaaaaaa aaaaaaaa .* 0090 003c00c0 003c803f 00c0803f 55555555 .* + 00a0 007c807f 0000807f 00000000 0000f07f .* + 00b0 00000000 00000080 ff7f0000 44444444 .* + 00c0 007c807f 0000807f 00000000 0000f07f .* + 00d0 00000000 00000080 ff7f0000 33333333 .* + 00e0 00fc80ff 000080ff 00000000 0000f0ff .* + 00f0 00000000 00000080 ffff0000 22222222 .* + 0100 ff7fff7f ffffff7f ffffffff ffffff7f .* + 0110 ffffffff ffffffff ff7f0000 44444444 .* + 0120 ff7fff7f ffffff7f ffffffff ffffff7f .* + 0130 ffffffff ffffffff ff7f0000 33333333 .* + 0140 ffffffff ffffffff ffffffff ffffffff .* + 0150 ffffffff ffffffff ffff0000 22222222 .* + 0160 ff7fff7f ffffff7f ffffffff ffffff7f .* + 0170 ffffffff ffffffff ff7f0000 44444444 .* + 0180 ff7fff7f ffffff7f ffffffff ffffff7f .* + 0190 ffffffff ffffffff ff7f0000 33333333 .* + 01a0 ffffffff ffffffff ffffffff ffffffff .* + 01b0 ffffffff ffffffff ffff0000 22222222 .* + 01c0 ff7dbf7f ffffbf7f ffffffff fffff77f .* + 01d0 ffffffff ffffffbf ff7f0000 44444444 .* + 01e0 ff7dbf7f ffffbf7f ffffffff fffff77f .* + 01f0 ffffffff ffffffbf ff7f0000 33333333 .* + 0200 fffdbfff ffffbfff ffffffff fffff7ff .* + 0210 ffffffff ffffffbf ffff0000 22222222 .* diff --git a/gas/testsuite/gas/i386/fp-elf64.d b/gas/testsuite/gas/i386/fp-elf64.d index fc96e53490f..2b3b6b8b29a 100644 --- a/gas/testsuite/gas/i386/fp-elf64.d +++ b/gas/testsuite/gas/i386/fp-elf64.d @@ -15,3 +15,27 @@ Contents of section .data: 0070 00000000 00000080 fdbf0000 00000000 .* 0080 00000000 00000080 ff030000 00000000 .* 0090 003c00c0 003c803f 00c0803f 55555555 .* + 00a0 007c807f 0000807f 00000000 0000f07f .* + 00b0 00000000 00000080 ff7f0000 00000000 .* + 00c0 007c807f 0000807f 00000000 0000f07f .* + 00d0 00000000 00000080 ff7f0000 00000000 .* + 00e0 00fc80ff 000080ff 00000000 0000f0ff .* + 00f0 00000000 00000080 ffff0000 00000000 .* + 0100 ff7fff7f ffffff7f ffffffff ffffff7f .* + 0110 ffffffff ffffffff ff7f0000 00000000 .* + 0120 ff7fff7f ffffff7f ffffffff ffffff7f .* + 0130 ffffffff ffffffff ff7f0000 00000000 .* + 0140 ffffffff ffffffff ffffffff ffffffff .* + 0150 ffffffff ffffffff ffff0000 00000000 .* + 0160 ff7fff7f ffffff7f ffffffff ffffff7f .* + 0170 ffffffff ffffffff ff7f0000 00000000 .* + 0180 ff7fff7f ffffff7f ffffffff ffffff7f .* + 0190 ffffffff ffffffff ff7f0000 00000000 .* + 01a0 ffffffff ffffffff ffffffff ffffffff .* + 01b0 ffffffff ffffffff ffff0000 00000000 .* + 01c0 ff7dbf7f ffffbf7f ffffffff fffff77f .* + 01d0 ffffffff ffffffbf ff7f0000 00000000 .* + 01e0 ff7dbf7f ffffbf7f ffffffff fffff77f .* + 01f0 ffffffff ffffffbf ff7f0000 00000000 .* + 0200 fffdbfff ffffbfff ffffffff fffff7ff .* + 0210 ffffffff ffffffbf ffff0000 00000000 .* diff --git a/gas/testsuite/gas/i386/fp.d b/gas/testsuite/gas/i386/fp.d index c2db0d25343..ad0afcd60b8 100644 --- a/gas/testsuite/gas/i386/fp.d +++ b/gas/testsuite/gas/i386/fp.d @@ -13,3 +13,27 @@ Contents of section .data: 0060 00000000 00000080 fe3f0000 00000000 .* 0070 0080fdbf 00000000 00000080 ff03aaaa .* 0080 003c00c0 003c803f 00c0803f 55555555 .* + 0090 007c807f 0000807f 00000000 0000f07f .* + 00a0 00000000 00000080 ff7f4444 44444444 .* + 00b0 007c807f 0000807f 00000000 0000f07f .* + 00c0 00000000 00000080 ff7f3333 33333333 .* + 00d0 00fc80ff 000080ff 00000000 0000f0ff .* + 00e0 00000000 00000080 ffff2222 22222222 .* + 00f0 ff7fff7f ffffff7f ffffffff ffffff7f .* + 0100 ffffffff ffffffff ff7f4444 44444444 .* + 0110 ff7fff7f ffffff7f ffffffff ffffff7f .* + 0120 ffffffff ffffffff ff7f3333 33333333 .* + 0130 ffffffff ffffffff ffffffff ffffffff .* + 0140 ffffffff ffffffff ffff2222 22222222 .* + 0150 ff7fff7f ffffff7f ffffffff ffffff7f .* + 0160 ffffffff ffffffff ff7f4444 44444444 .* + 0170 ff7fff7f ffffff7f ffffffff ffffff7f .* + 0180 ffffffff ffffffff ff7f3333 33333333 .* + 0190 ffffffff ffffffff ffffffff ffffffff .* + 01a0 ffffffff ffffffff ffff2222 22222222 .* + 01b0 ff7dbf7f ffffbf7f ffffffff fffff77f .* + 01c0 ffffffff ffffffbf ff7f4444 44444444 .* + 01d0 ff7dbf7f ffffbf7f ffffffff fffff77f .* + 01e0 ffffffff ffffffbf ff7f3333 33333333 .* + 01f0 fffdbfff ffffbfff ffffffff fffff7ff .* + 0200 ffffffff ffffffbf ffff2222 22222222 .* diff --git a/gas/testsuite/gas/i386/fp.s b/gas/testsuite/gas/i386/fp.s index 8c5abb490b9..a63464b6cd2 100644 --- a/gas/testsuite/gas/i386/fp.s +++ b/gas/testsuite/gas/i386/fp.s @@ -33,3 +33,87 @@ .hfloat 1, -2, 0x:3c00 .bfloat16 1, -2, 0x:3f80 .p2align 4,0x55 + + .hfloat Inf + .bfloat16 Inf + .single Inf + .double Inf + .tfloat Inf + .p2align 4,0x44 + + .hfloat +Inf + .bfloat16 +Inf + .single +Inf + .double +Inf + .tfloat +Inf + .p2align 4,0x33 + + .hfloat -Inf + .bfloat16 -Inf + .single -Inf + .double -Inf + .tfloat -Inf + .p2align 4,0x22 + + .hfloat NaN + .bfloat16 NaN + .single NaN + .double NaN + .tfloat NaN + .p2align 4,0x44 + + .hfloat +NaN + .bfloat16 +NaN + .single +NaN + .double +NaN + .tfloat +NaN + .p2align 4,0x33 + + .hfloat -NaN + .bfloat16 -NaN + .single -NaN + .double -NaN + .tfloat -NaN + .p2align 4,0x22 + + .hfloat QNaN + .bfloat16 QNaN + .single QNaN + .double QNaN + .tfloat QNaN + .p2align 4,0x44 + + .hfloat +QNaN + .bfloat16 +QNaN + .single +QNaN + .double +QNaN + .tfloat +QNaN + .p2align 4,0x33 + + .hfloat -QNaN + .bfloat16 -QNaN + .single -QNaN + .double -QNaN + .tfloat -QNaN + .p2align 4,0x22 + + .hfloat SNaN + .bfloat16 SNaN + .single SNaN + .double SNaN + .tfloat SNaN + .p2align 4,0x44 + + .hfloat +SNaN + .bfloat16 +SNaN + .single +SNaN + .double +SNaN + .tfloat +SNaN + .p2align 4,0x33 + + .hfloat -SNaN + .bfloat16 -SNaN + .single -SNaN + .double -SNaN + .tfloat -SNaN + .p2align 4,0x22 -- 2.30.2