[10/11] gas: support NaN flavors

Message ID 1a6edd12-4cf4-aced-2e46-626f7497f874@suse.com
State New
Headers show
Series
  • gas: adjustments to floating point data directives handling
Related show

Commit Message

Alan Modra via Binutils July 23, 2021, 6:59 a.m.
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.

Comments

Andreas Schwab July 23, 2021, 8:19 a.m. | #1
On Jul 23 2021, Jan Beulich via Binutils wrote:

> 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.


Isn't that what the i387 generates as the default NaN?

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."
Alan Modra via Binutils July 23, 2021, 12:57 p.m. | #2
On 23.07.2021 10:19, Andreas Schwab wrote:
> On Jul 23 2021, Jan Beulich via Binutils wrote:

> 

>> 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 chosen for an unknown

>> reason.

> 

> Isn't that what the i387 generates as the default NaN?


One of these two forms yes (and you don't clarify which of the
two you mean). In any event there was an inconsistency. Which
way to resolve it is open for discussion of course.

Jan
Andreas Schwab July 23, 2021, 1:28 p.m. | #3
See libiberty/floatformat.c for a description of the various float
formats.

Andreas.

-- 
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."
Alan Modra via Binutils July 23, 2021, 2:48 p.m. | #4
On 23.07.2021 15:28, Andreas Schwab wrote:
> See libiberty/floatformat.c for a description of the various float

> formats.


I guess there are better sources of information for this, like the
IEEE standard or vendor docs. I'm afraid you didn't get across the
point you were trying to make with your earlier reply.

Jan

Patch

--- 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