diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/s390/s390.md | 17 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/s390/dfp-1.c | 23 |
4 files changed, 49 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0cfc1e2eadd..6e85072e916 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,13 @@ 2016-03-11 Andreas Krebbel <krebbel@linux.vnet.ibm.com> + * config/s390/s390.md ("trunctddd2"): Turn former define_insn into + define_expand. + ("*trunctddd2"): New pattern definition. + ("trunctdsd2"): Set prep_for_short_prec rounding mode for the + TD->DD truncation. + +2016-03-11 Andreas Krebbel <krebbel@linux.vnet.ibm.com> + * config/s390/s390.md (BFP_RND_*, DFP_RND_*): Add new constant definitions for BFP and DFP rounding modes. ("fixuns_truncdddi2", "fixuns_trunctddi2") diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md index 185a3f8511b..5a9f1c8a606 100644 --- a/gcc/config/s390/s390.md +++ b/gcc/config/s390/s390.md @@ -4847,12 +4847,22 @@ ; trunctddd2 and truncddsd2 instruction pattern(s). ; -(define_insn "trunctddd2" + +(define_expand "trunctddd2" + [(parallel + [(set (match_operand:DD 0 "register_operand" "") + (float_truncate:DD (match_operand:TD 1 "register_operand" ""))) + (unspec:DI [(const_int DFP_RND_CURRENT)] UNSPEC_ROUND) + (clobber (scratch:TD))])] + "TARGET_HARD_DFP") + +(define_insn "*trunctddd2" [(set (match_operand:DD 0 "register_operand" "=f") (float_truncate:DD (match_operand:TD 1 "register_operand" "f"))) - (clobber (match_scratch:TD 2 "=f"))] + (unspec:DI [(match_operand:DI 2 "const_mask_operand" "I")] UNSPEC_ROUND) + (clobber (match_scratch:TD 3 "=f"))] "TARGET_HARD_DFP" - "ldxtr\t%2,0,%1,0\;ldr\t%0,%2" + "ldxtr\t%3,%2,%1,0\;ldr\t%0,%3" [(set_attr "length" "6") (set_attr "type" "ftruncdd")]) @@ -4868,6 +4878,7 @@ [(parallel [(set (match_dup 3) (float_truncate:DD (match_operand:TD 1 "register_operand" ""))) + (unspec:DI [(const_int DFP_RND_PREP_FOR_SHORT_PREC)] UNSPEC_ROUND) (clobber (match_scratch:TD 2 ""))]) (set (match_operand:SD 0 "register_operand" "") (float_truncate:SD (match_dup 3)))] diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index be04568f5dd..254b6bccff3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2016-03-11 Andreas Krebbel <krebbel@linux.vnet.ibm.com> + + * gcc.target/s390/dfp-1.c: New test. + 2016-03-10 Nick Clifton <nickc@redhat.com> PR target/70044 diff --git a/gcc/testsuite/gcc.target/s390/dfp-1.c b/gcc/testsuite/gcc.target/s390/dfp-1.c new file mode 100644 index 00000000000..109d9fb63f8 --- /dev/null +++ b/gcc/testsuite/gcc.target/s390/dfp-1.c @@ -0,0 +1,23 @@ +/* We do not have a direct conversion instruction from 128 bit DFP to + 32 bit DFP so this needs to be done in two steps. The first needs + to be done with the "prepare for shorter precision rounding mode" + in order to produce a correct result. Otherwise the 8th digit of + the number will change from 4 to 5 in the first rounding step which + then will turn the last digit of the 32 bit DFP number (the 3) into + a 4. Although with direct rounding it would stay a 3. */ + +/* { dg-do run } */ +/* { dg-options "-O3 -march=z10 -mzarch" } */ + +_Decimal32 __attribute__((noinline)) +foo (_Decimal128 a) +{ + return (_Decimal32)a; +} + +int +main () +{ + if (foo (1.23456349999999999DL) != 1.234563DF) + __builtin_abort (); +} |