[PATCH 10/11] gas: support NaN flavors

Jan Beulich jbeulich@suse.com
Fri Jul 23 06:59:02 GMT 2021


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.

--- a/gas/atof-generic.c
+++ b/gas/atof-generic.c
@@ -113,11 +113,29 @@ atof_generic (/* return pointer to just
 
   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;
--- 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
       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
 	  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
 	}
       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
 	  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"));
 
--- a/gas/config/tc-tic4x.c
+++ b/gas/config/tc-tic4x.c
@@ -384,8 +384,10 @@ tic4x_gen_to_words (FLONUM_TYPE flonum,
   /* 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;
--- 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 */
--- 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
--- 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  .*
--- 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  .*
--- 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  .*
--- 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



More information about the Binutils mailing list