According to IEEE 754 2008 4.3 'Rounding-direction attributes' the
rounding mode of the target format needs to be used. By not setting
the value so far we have always used the DFP rounding mode.

gcc/ChangeLog:

2018-09-06  Andreas Krebbel  <kreb...@linux.ibm.com>

        * config/s390/s390.md (PFPO_RND_MODE_DFP, PFPO_RND_MODE_BFP): New
        constants.
        ("trunc<BFP:mode><DFP_ALL:mode>2")
        ("trunc<DFP_ALL:mode><BFP:mode>2")
        ("extend<BFP:mode><DFP_ALL:mode>2")
        ("extend<DFP_ALL:mode><BFP:mode>2"): Set proper rounding mode
        according to the target operand type.

gcc/testsuite/ChangeLog:

2018-09-06  Andreas Krebbel  <kreb...@linux.ibm.com>

        * gcc.target/s390/dfp_to_bfp_rounding.c: New test.
---
 gcc/config/s390/s390.md                            | 28 ++++++++++++++++++---
 .../gcc.target/s390/dfp_to_bfp_rounding.c          | 29 ++++++++++++++++++++++
 2 files changed, 53 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/dfp_to_bfp_rounding.c

diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index ddf8608..537ed35 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -404,6 +404,10 @@
    ; Bitposition of operand types
    (PFPO_OP0_TYPE_SHIFT          16)
    (PFPO_OP1_TYPE_SHIFT           8)
+   ; Decide whether current DFP or BFD rounding mode should be used
+   ; for the conversion.
+   (PFPO_RND_MODE_DFP             0)
+   (PFPO_RND_MODE_BFP             1)
   ])
 
 ; Immediate operands for tbegin and tbeginc
@@ -5377,9 +5381,13 @@
 {
   HOST_WIDE_INT flags;
 
+  /* According to IEEE 754 2008 4.3 'Rounding-direction attributes' the
+     rounding mode of the target format needs to be used.  */
+
   flags = (PFPO_CONVERT |
            PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP0_TYPE_SHIFT |
-           PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP1_TYPE_SHIFT);
+           PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP1_TYPE_SHIFT |
+          PFPO_RND_MODE_DFP);
 
   operands[2] = GEN_INT (flags);
 })
@@ -5399,9 +5407,13 @@
 {
   HOST_WIDE_INT flags;
 
+  /* According to IEEE 754 2008 4.3 'Rounding-direction attributes' the
+     rounding mode of the target format needs to be used.  */
+
   flags = (PFPO_CONVERT |
            PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP0_TYPE_SHIFT |
-           PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP1_TYPE_SHIFT);
+           PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP1_TYPE_SHIFT |
+          PFPO_RND_MODE_BFP);
 
   operands[2] = GEN_INT (flags);
 })
@@ -5442,9 +5454,13 @@
 {
   HOST_WIDE_INT flags;
 
+  /* According to IEEE 754 2008 4.3 'Rounding-direction attributes' the
+     rounding mode of the target format needs to be used.  */
+
   flags = (PFPO_CONVERT |
            PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP0_TYPE_SHIFT |
-           PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP1_TYPE_SHIFT);
+           PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP1_TYPE_SHIFT |
+          PFPO_RND_MODE_DFP);
 
   operands[2] = GEN_INT (flags);
 })
@@ -5464,9 +5480,13 @@
 {
   HOST_WIDE_INT flags;
 
+  /* According to IEEE 754 2008 4.3 'Rounding-direction attributes' the
+     rounding mode of the target format needs to be used.  */
+
   flags = (PFPO_CONVERT |
            PFPO_OP_TYPE_<BFP:MODE> << PFPO_OP0_TYPE_SHIFT |
-           PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP1_TYPE_SHIFT);
+           PFPO_OP_TYPE_<DFP_ALL:MODE> << PFPO_OP1_TYPE_SHIFT |
+          PFPO_RND_MODE_BFP);
 
   operands[2] = GEN_INT (flags);
 })
diff --git a/gcc/testsuite/gcc.target/s390/dfp_to_bfp_rounding.c 
b/gcc/testsuite/gcc.target/s390/dfp_to_bfp_rounding.c
new file mode 100644
index 0000000..9a32abf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/dfp_to_bfp_rounding.c
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -march=z10" } */
+
+/* According to IEEE 754 2008 4.3 Conversion operations between
+   different radixes must use the rounding mode of the target radix.
+   On S/390 this means passing the right value in GPR0 to PFPO
+   instruction.  */
+
+#include <fenv.h>
+
+double __attribute__((noclone,noinline))
+convert (_Decimal64 in)
+{
+  return (double)in;
+}
+
+int
+main ()
+{
+  fesetround (FE_UPWARD);
+
+  if (convert (1e-325DD) != __DBL_DENORM_MIN__)
+    __builtin_abort ();
+
+  fesetround (FE_DOWNWARD);
+
+  if (convert (-1e-325DD) != -__DBL_DENORM_MIN__)
+    __builtin_abort ();
+}
-- 
2.7.4

Reply via email to