Commit 432d4670 by Andreas Krebbel Committed by Andreas Krebbel

S/390: Fix rounding for _Decimal128 to _Decimal32 conversion

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.

gcc/ChangeLog:

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.

gcc/testsuite/ChangeLog:

2016-03-11  Andreas Krebbel  <krebbel@linux.vnet.ibm.com>

	* gcc.target/s390/dfp-1.c: New test.

From-SVN: r234134
parent ae8e301e
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")
......
......@@ -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)))]
......
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
......
/* 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 ();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment