[v3] rs6000: Add buildin for mffscrn instructions
Checks
Commit Message
Kewen, Segher, GCC maintainers:
Version 3, fixed various issues noted by Kewen. Retested on Power 10.
No regression issues.
Version 2, Fixed an issue with the test case. The dg-options line was
missing.
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 builtin for mffscrn instructions
This patch adds overloaded __builtin_mffscrn for the move From FPSCR
Control & Set RN 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 | 9 +-
gcc/config/rs6000/rs6000-overload.def | 5 +
gcc/doc/extend.texi | 10 ++
.../gcc.target/powerpc/builtin-mffscrn.c | 106 ++++++++++++++++++
4 files changed, 129 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/gcc.target/powerpc/builtin-mffscrn.c
@@ -2849,6 +2849,14 @@
const signed int __builtin_vsx_scalar_extract_exp (double);
VSEEDP xsxexpdp_si {}
+; Immediate instruction only uses the least significant two bits of the
+; const int.
+ double __builtin_mffscrni (const int<2>);
+ MFFSCRNI rs6000_mffscrni {nosoft}
+
+ double __builtin_mffscrnd (double);
+ MFFSCRNF rs6000_mffscrn {nosoft}
+
[power9-64]
void __builtin_altivec_xst_len_r (vsc, void *, long);
XST_LEN_R xst_len_r {}
@@ -2875,7 +2883,6 @@
pure vsc __builtin_vsx_xl_len_r (void *, signed long);
XL_LEN_R xl_len_r {}
-
; Builtins requiring hardware support for IEEE-128 floating-point.
[ieee128-hw]
fpmath _Float128 __builtin_addf128_round_to_odd (_Float128, _Float128);
@@ -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);
@@ -18274,6 +18274,16 @@ The @code{__builtin_recipdiv}, and @code{__builtin_recipdivf}
functions generate multiple instructions to implement division using
the reciprocal estimate instructions.
+double __builtin_mffscrn (const int);
+double __builtin_mffscrn (double);
+
+The @code{__builtin_mffscrn} returns the contents of the control bits DRN, VE,
+OE, UE, ZE, XE, NI, RN in the FPSCR are returned with RN updated appropriately.
+In the case of the const int variant of the builtin, RN is set to the 2-bit
+value specified in the builtin. In the case of the double builtin variant, the
+2-bit value in the double argument that corresponds to the RN location in the
+FPSCR is updated.
+
The following functions require @option{-mhard-float} and
@option{-mmultiple} options.
new file mode 100644
@@ -0,0 +1,106 @@
+/* { dg-do run } */
+/* { dg-require-effective-target p9modulo_hw } */
+/* { dg-options "-mdejagnu-cpu=power9" } */
+
+#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
+}