[aarch64] .bfloat16 directive for AArch64 [7/10]

Message ID 5db8634c.1c69fb81.5d03c.c4ddSMTPIN_ADDED_MISSING@mx.google.com
State New
Headers show
Series
  • [aarch64] .bfloat16 directive for AArch64 [7/10]
Related show

Commit Message

Mihail Ionescu Oct. 29, 2019, 3:20 p.m.
Hi,

This patch is part of a series that adds support for Armv8.6-A
(Matrix Multiply and BFloat16 extensions) to binutils.

This patch implements the '.bfloat' directive for the AArch64 backend.

The syntax for the directive is:
  .bfloat16 <0-n numbers>
e.g.
  .bfloat16 12.0
  .bfloat16 0.123, 1.0, NaN, 5

This is implemented by utilizing the ieee_atof_detail function in order to encode the slightly
different bfloat16 format.

Added testcases to verify the correct encoding for various bfloat16 values (NaN, Infinity (+ & -),
normals, subnormals etc...).

Cross compiled and tested on aarch64-none-elf and aarch64-none-linux-gnu with no issues.

gas/ChangeLog:


2019-10-29  Mihail Ionescu  <mihail.ionescu@arm.com>
2019-10-29  Barnaby Wilks  <barnaby.wilks@arm.com>

	* config/tc-aarch64.c (md_atof): Add encoding for the bfloat16 format.
	* testsuite/gas/aarch64/bfloat16-directive-le.d: New test.
	* testsuite/gas/aarch64/bfloat16-directive-be.d: New test.
	* testsuite/gas/aarch64/bfloat16-directive.s: New test.

Is it ok for trunk?


Regards,
Mihail


###############     Attachment also inlined for ease of reply    ###############
diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 78eda58ee1e8b99f710034da47b601f4b0981383..dbf51c1f3212fd2c1fe116e23a3ee89a85e95fd1 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -635,6 +635,54 @@ my_get_expression (expressionS * ep, char **str, int prefix_mode,
 const char *
 md_atof (int type, char *litP, int *sizeP)
 {
+  /* If this is a bfloat16 type, then parse it slightly differently -
+     as it does not follow the IEEE standard exactly.  */
+  if (type == 'b')
+    {
+      char * t;
+      LITTLENUM_TYPE words[MAX_LITTLENUMS];
+      FLONUM_TYPE generic_float;
+
+      t = atof_ieee_detail (input_line_pointer, 1, 8, words, &generic_float);
+
+      if (t)
+	input_line_pointer = t;
+      else
+	return _("invalid floating point number");
+
+      switch (generic_float.sign)
+	{
+	/* Is +Inf.  */
+	case 'P':
+	  words[0] = 0x7f80;
+	  break;
+
+	/* Is -Inf.  */
+	case 'N':
+	  words[0] = 0xff80;
+	  break;
+
+	/* Is NaN.  */
+	/* bfloat16 has two types of NaN - quiet and signalling.
+	   Quiet NaN has bit[6] == 1 && faction != 0, whereas
+	   signalling Nan's have bit[0] == 0 && fraction != 0.
+	   Chose this specific encoding as it is the same form
+	   as used by other IEEE 754 encodings in GAS.  */
+	case 0:
+	  words[0] = 0x7fff;
+	  break;
+
+	default:
+	  break;
+	}
+
+      *sizeP = 2;
+
+      md_number_to_chars (litP, (valueT) words[0], sizeof (LITTLENUM_TYPE));
+
+      return NULL;
+    }
+
   return ieee_md_atof (type, litP, sizeP, target_big_endian);
 }
 
@@ -2107,6 +2155,7 @@ const pseudo_typeS md_pseudo_table[] = {
   {"variant_pcs", s_variant_pcs, 0},
 #endif
   {"float16", float_cons, 'h'},
+  {"bfloat16", float_cons, 'b'},
   {0, 0, 0}
 };
 
diff --git a/gas/testsuite/gas/aarch64/bfloat16-directive-be.d b/gas/testsuite/gas/aarch64/bfloat16-directive-be.d
new file mode 100644
index 0000000000000000000000000000000000000000..132d04e44fad44b1b040c82df70e42ce11e6b483
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/bfloat16-directive-be.d
@@ -0,0 +1,11 @@
+# name: Big endian bfloat16 literal directives
+# source: bfloat16-directive.s
+# as: -mbig-endian
+# objdump: -s --section=.data
+
+.*: +file format .*
+
+Contents of section \.data:
+ 0000 41403dfc 000042f7 8000c2f7 7fff7f80  .*
+ 0010 ff807f7f ff7f0080 80800001 8001007f  .*
+ 0020 807f3f80 bf804000 c000               .*
diff --git a/gas/testsuite/gas/aarch64/bfloat16-directive-le.d b/gas/testsuite/gas/aarch64/bfloat16-directive-le.d
new file mode 100644
index 0000000000000000000000000000000000000000..f22d610d84bfd1961affdbdedbb9be7679844b9f
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/bfloat16-directive-le.d
@@ -0,0 +1,11 @@
+# name: Little endian bfloat16 literal directives
+# source: bfloat16-directive.s
+# as: -mlittle-endian
+# objdump: -s --section=.data
+
+.*: +file format .*
+
+Contents of section \.data:
+ 0000 4041fc3d 0000f742 0080f7c2 ff7f807f  .*
+ 0010 80ff7f7f 7fff8000 80800100 01807f00  .*
+ 0020 7f80803f 80bf0040 00c0               .*
diff --git a/gas/testsuite/gas/aarch64/bfloat16-directive.s b/gas/testsuite/gas/aarch64/bfloat16-directive.s
new file mode 100644
index 0000000000000000000000000000000000000000..66e17e4fc7da9b08098a0ca03660df2b5ab4f021
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/bfloat16-directive.s
@@ -0,0 +1,19 @@
+.data
+	.bfloat16 12.0
+	.bfloat16 0.123
+	.bfloat16 +0.0
+	.bfloat16 123.4
+	.bfloat16 -0.0
+	.bfloat16 -123.4
+	.bfloat16 NaN
+	.bfloat16 Inf
+	.bfloat16 -Inf
+	.bfloat16 3.390e+38
+	.bfloat16 -3.390e+38
+	.bfloat16 1.175e-38
+	.bfloat16 -1.175e-38
+	.bfloat16 9.194e-41
+	.bfloat16 -9.194e-41
+	.bfloat16 1.167e-38
+	.bfloat16 -1.167e-38
+	.bfloat16 1.0, -1, 2.0, -2

Patch

diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c
index 78eda58ee1e8b99f710034da47b601f4b0981383..dbf51c1f3212fd2c1fe116e23a3ee89a85e95fd1 100644
--- a/gas/config/tc-aarch64.c
+++ b/gas/config/tc-aarch64.c
@@ -635,6 +635,54 @@  my_get_expression (expressionS * ep, char **str, int prefix_mode,
 const char *
 md_atof (int type, char *litP, int *sizeP)
 {
+  /* If this is a bfloat16 type, then parse it slightly differently -
+     as it does not follow the IEEE standard exactly.  */
+  if (type == 'b')
+    {
+      char * t;
+      LITTLENUM_TYPE words[MAX_LITTLENUMS];
+      FLONUM_TYPE generic_float;
+
+      t = atof_ieee_detail (input_line_pointer, 1, 8, words, &generic_float);
+
+      if (t)
+	input_line_pointer = t;
+      else
+	return _("invalid floating point number");
+
+      switch (generic_float.sign)
+	{
+	/* Is +Inf.  */
+	case 'P':
+	  words[0] = 0x7f80;
+	  break;
+
+	/* Is -Inf.  */
+	case 'N':
+	  words[0] = 0xff80;
+	  break;
+
+	/* Is NaN.  */
+	/* bfloat16 has two types of NaN - quiet and signalling.
+	   Quiet NaN has bit[6] == 1 && faction != 0, whereas
+	   signalling Nan's have bit[0] == 0 && fraction != 0.
+	   Chose this specific encoding as it is the same form
+	   as used by other IEEE 754 encodings in GAS.  */
+	case 0:
+	  words[0] = 0x7fff;
+	  break;
+
+	default:
+	  break;
+	}
+
+      *sizeP = 2;
+
+      md_number_to_chars (litP, (valueT) words[0], sizeof (LITTLENUM_TYPE));
+
+      return NULL;
+    }
+
   return ieee_md_atof (type, litP, sizeP, target_big_endian);
 }
 
@@ -2107,6 +2155,7 @@  const pseudo_typeS md_pseudo_table[] = {
   {"variant_pcs", s_variant_pcs, 0},
 #endif
   {"float16", float_cons, 'h'},
+  {"bfloat16", float_cons, 'b'},
   {0, 0, 0}
 };
 


diff --git a/gas/testsuite/gas/aarch64/bfloat16-directive-be.d b/gas/testsuite/gas/aarch64/bfloat16-directive-be.d
new file mode 100644
index 0000000000000000000000000000000000000000..132d04e44fad44b1b040c82df70e42ce11e6b483
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/bfloat16-directive-be.d
@@ -0,0 +1,11 @@ 
+# name: Big endian bfloat16 literal directives
+# source: bfloat16-directive.s
+# as: -mbig-endian
+# objdump: -s --section=.data
+
+.*: +file format .*
+
+Contents of section \.data:
+ 0000 41403dfc 000042f7 8000c2f7 7fff7f80  .*
+ 0010 ff807f7f ff7f0080 80800001 8001007f  .*
+ 0020 807f3f80 bf804000 c000               .*
diff --git a/gas/testsuite/gas/aarch64/bfloat16-directive-le.d b/gas/testsuite/gas/aarch64/bfloat16-directive-le.d
new file mode 100644
index 0000000000000000000000000000000000000000..f22d610d84bfd1961affdbdedbb9be7679844b9f
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/bfloat16-directive-le.d
@@ -0,0 +1,11 @@ 
+# name: Little endian bfloat16 literal directives
+# source: bfloat16-directive.s
+# as: -mlittle-endian
+# objdump: -s --section=.data
+
+.*: +file format .*
+
+Contents of section \.data:
+ 0000 4041fc3d 0000f742 0080f7c2 ff7f807f  .*
+ 0010 80ff7f7f 7fff8000 80800100 01807f00  .*
+ 0020 7f80803f 80bf0040 00c0               .*
diff --git a/gas/testsuite/gas/aarch64/bfloat16-directive.s b/gas/testsuite/gas/aarch64/bfloat16-directive.s
new file mode 100644
index 0000000000000000000000000000000000000000..66e17e4fc7da9b08098a0ca03660df2b5ab4f021
--- /dev/null
+++ b/gas/testsuite/gas/aarch64/bfloat16-directive.s
@@ -0,0 +1,19 @@ 
+.data
+	.bfloat16 12.0
+	.bfloat16 0.123
+	.bfloat16 +0.0
+	.bfloat16 123.4
+	.bfloat16 -0.0
+	.bfloat16 -123.4
+	.bfloat16 NaN
+	.bfloat16 Inf
+	.bfloat16 -Inf
+	.bfloat16 3.390e+38
+	.bfloat16 -3.390e+38
+	.bfloat16 1.175e-38
+	.bfloat16 -1.175e-38
+	.bfloat16 9.194e-41
+	.bfloat16 -9.194e-41
+	.bfloat16 1.167e-38
+	.bfloat16 -1.167e-38
+	.bfloat16 1.0, -1, 2.0, -2