rs6000: Add buildin for mffscrn instructions

Message ID a1756a8e41b03138f8db58899799a4539812ecf1.camel@us.ibm.com
State Accepted
Headers
Series rs6000: Add buildin for mffscrn instructions |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Carl Love April 13, 2023, 8:47 p.m. UTC
  GCC maintainers:

The following patch adds an overloaded builtin.  There are two possible
arguments for the builtin.  The builtin definitions are:

  double __builtin_mffscrn (unsigned long int);
  double __builtin_mffscrn (double);

The patch has been tested on Power 10 with no regressions.  

Please let me know if the patch is acceptable for mainline.  Thanks.

                    Carl 

-----------------------------------
rs6000: Add buildin for mffscrn instructions

This patch adds overloaded __builtin_mffscrn for the move From FPSCR
Control & Set R instruction with an immediate argument.  It also adds the
builtin with a floating point register argument.  A new runnable test is
added for the new builtin.

gcc/

	* config/rs6000/rs6000-builtins.def (__builtin_mffscrni,
	__builtin_mffscrnd): Add builtin definitions.
	* config/rs6000/rs6000-overload.def (__builtin_mffscrn): Add
	overloaded definition.
	* doc/extend.texi: Add documentation for __builtin_mffscrn.

gcc/testsuite/

	* gcc.target/powerpc/builtin-mffscrn.c: Add testcase for new
	builtin.
---
 gcc/config/rs6000/rs6000-builtins.def         |   7 ++
 gcc/config/rs6000/rs6000-overload.def         |   5 +
 gcc/doc/extend.texi                           |   8 ++
 .../gcc.target/powerpc/builtin-mffscrn.c      | 105 ++++++++++++++++++
 4 files changed, 125 insertions(+)
 create mode 100644 gcc/testsuite/gcc.target/powerpc/builtin-mffscrn.c
  

Patch

diff --git a/gcc/config/rs6000/rs6000-builtins.def b/gcc/config/rs6000/rs6000-builtins.def
index 03fb194b151..6247cb6c0fe 100644
--- a/gcc/config/rs6000/rs6000-builtins.def
+++ b/gcc/config/rs6000/rs6000-builtins.def
@@ -2863,6 +2863,13 @@ 
   pure vsc __builtin_vsx_xl_len_r (void *, signed long);
     XL_LEN_R xl_len_r {}
 
+; Immediate instruction only uses the least significant two bits of the
+; const int.
+  double __builtin_mffscrni (const int<2>);
+    MFFSCRNI rs6000_mffscrni {}
+
+  double __builtin_mffscrnd (double);
+    MFFSCRNF rs6000_mffscrn {}
 
 ; Builtins requiring hardware support for IEEE-128 floating-point.
 [ieee128-hw]
diff --git a/gcc/config/rs6000/rs6000-overload.def b/gcc/config/rs6000/rs6000-overload.def
index c582490c084..adda2df69ea 100644
--- a/gcc/config/rs6000/rs6000-overload.def
+++ b/gcc/config/rs6000/rs6000-overload.def
@@ -78,6 +78,11 @@ 
 ; like after a required newline, but nowhere else.  Lines beginning with
 ; a semicolon are also treated as blank lines.
 
+[MFFSCR, __builtin_mffscrn, __builtin_mffscrn]
+  double __builtin_mffscrn (const int<2>);
+    MFFSCRNI
+  double __builtin_mffscrn (double);
+    MFFSCRNF
 
 [BCDADD, __builtin_bcdadd, __builtin_vec_bcdadd]
   vsq __builtin_vec_bcdadd (vsq, vsq, const int);
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 3adb67aa47a..168d439c0e4 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -18317,6 +18317,9 @@  int __builtin_dfp_dtstsfi_ov_td (unsigned int comparison, _Decimal128 value);
 
 double __builtin_mffsl(void);
 
+double __builtin_mffscrn (unsigned long int);
+double __builtin_mffscrn (double);
+
 @end smallexample
 The @code{__builtin_byte_in_set} function requires a
 64-bit environment supporting ISA 3.0 or later.  This function returns
@@ -18373,6 +18376,11 @@  the FPSCR.  The instruction is a lower latency version of the @code{mffs}
 instruction.  If the @code{mffsl} instruction is not available, then the
 builtin uses the older @code{mffs} instruction to read the FPSCR.
 
+The @code{__builtin_mffscrn} returns the contents of the control bits in the
+FPSCR, bits 29:31 (DRN) and bits 56:63 (VE, OE, UE, ZE, XE, NI, RN).  The
+contents of bits [62:63] of the unsigned long int or double argument are placed
+into bits [62:63] of the FPSCR (RN).
+
 @node Basic PowerPC Built-in Functions Available on ISA 3.1
 @subsubsection Basic PowerPC Built-in Functions Available on ISA 3.1
 
diff --git a/gcc/testsuite/gcc.target/powerpc/builtin-mffscrn.c b/gcc/testsuite/gcc.target/powerpc/builtin-mffscrn.c
new file mode 100644
index 00000000000..433a9081499
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/builtin-mffscrn.c
@@ -0,0 +1,105 @@ 
+/* { dg-do run } */
+/* { dg-require-effective-target p9vector_hw } */
+
+#include <altivec.h>
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+#define MASK 0x3
+#define EXPECTED1 0x1
+#define EXPECTED2 0x2
+
+void abort (void);
+
+int
+main()
+{
+  unsigned long mask, result, expected;
+  double double_arg;
+  
+  union convert_t {
+    double d;
+    unsigned long ul;
+  } val;
+
+  /* Test immediate version of __builtin_mffscrn. */
+  /* Read FPSCR and set RN bits in FPSCR[62:63]. */
+  val.d = __builtin_mffscrn (EXPECTED2);
+
+  /* Read FPSCR, bits [62:63] should have been set to 0x2 by previous builtin
+     call.  */
+  val.d = __builtin_mffscrn (EXPECTED1);
+  /* The expected result is the argument for the previous call to
+     __builtin_mffscrn.  */
+  expected = EXPECTED2;
+  result = MASK & val.ul;
+
+  if (EXPECTED2 != result)
+#ifdef DEBUG
+    printf("Result of mffscrn immediate doesn't match EXPECTED2.  Result was 0x%lx\n",
+	   result);
+#else
+    abort();
+#endif
+
+  /* Read FPSCR, bits [62:63] should have been set to 0x1 by previous builtin
+   call*/
+  val.d = __builtin_mffscrn (EXPECTED1);
+  expected = EXPECTED1;
+  result = MASK & val.ul;
+
+  if (EXPECTED1 != result)
+#ifdef DEBUG
+  printf("Result of mffscrn immediate doesn't match EXPECTED1.  Result was 0x%lx\n",
+	 result);
+#else
+  abort();
+#endif
+
+
+  /* Test double argument version of __builtin_mffscrn */
+  val.ul = EXPECTED2;
+  double_arg = val.d;
+
+  /* Read FPSCR and set RN bits in FPSCR[62:63]. */
+  val.d = __builtin_mffscrn (double_arg);
+
+  /* Read FPSCR, bits [62:63] should have been set to 0x2 by previous builtin  
+     call.  */
+
+  val.ul = EXPECTED1;
+  double_arg = val.d;
+
+  val.d = __builtin_mffscrn (double_arg);
+  /* The expected result is the argument for the previous call to
+     __builtin_mffscrn.  */
+  expected = EXPECTED2;
+  result = MASK & val.ul;
+
+  if (EXPECTED2 != result)
+#ifdef DEBUG
+    printf("Result of mffscrn double arg doesn't match EXPECTED2.  Result was 0x%lx\n",
+	   result);
+#else
+    abort();
+#endif
+
+  /* Read FPSCR, bits [62:63] should have been set to 0x1 by previous builtin
+   call*/
+  val.ul = EXPECTED1;
+  double_arg = val.d;
+
+  val.d = __builtin_mffscrn (double_arg);
+  expected = EXPECTED1;
+  result = MASK & val.ul;
+
+  if (EXPECTED1 != result)
+#ifdef DEBUG
+    printf("Result of mffscrn double arg doesn't match EXPECTED1.  Result was 0x%lx\n",
+	   result);
+#else
+    abort();
+#endif
+}