aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/rs6000
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2013-06-13 12:52:20 +0930
committerAlan Modra <amodra@gcc.gnu.org>2013-06-13 12:52:20 +0930
commit50751417db279b04c04a860b9476c215bd2a1a0a (patch)
tree334dcd6992f032c9ccae0cee61d50184e161e593 /gcc/config/rs6000
parentbcc193bf4616b02f5b8869fee13c34cf1d8984e8 (diff)
downloadgcc-50751417db279b04c04a860b9476c215bd2a1a0a.zip
gcc-50751417db279b04c04a860b9476c215bd2a1a0a.tar.gz
gcc-50751417db279b04c04a860b9476c215bd2a1a0a.tar.bz2
rs6000.h (LONG_DOUBLE_LARGE_FIRST): Define.
* config/rs6000/rs6000.h (LONG_DOUBLE_LARGE_FIRST): Define. * config/rs6000/rs6000.md (signbittf2): New insn. (extenddftf2_internal): Use LONG_DOUBLE_LARGE_FIRST. (abstf2_internal, cmptf_internal2): Likewise. * config/rs6000/spe.md (spe_abstf2_cmp, spe_abstf2_tst): Likewise. From-SVN: r200055
Diffstat (limited to 'gcc/config/rs6000')
-rw-r--r--gcc/config/rs6000/rs6000.h5
-rw-r--r--gcc/config/rs6000/rs6000.md47
-rw-r--r--gcc/config/rs6000/spe.md8
3 files changed, 50 insertions, 10 deletions
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index e557350..021e72a 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -715,6 +715,11 @@ extern unsigned char rs6000_recip_bits[];
instructions for them. Might as well be consistent with bits and bytes. */
#define WORDS_BIG_ENDIAN 1
+/* This says that for the IBM long double the larger magnitude double
+ comes first. It's really a two element double array, and arrays
+ don't index differently between little- and big-endian. */
+#define LONG_DOUBLE_LARGE_FIRST 1
+
#define MAX_BITS_PER_WORD 64
/* Width of a word, in units (bytes). */
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 8be86a4..a0f462a 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -5184,6 +5184,41 @@
"frsqrtes %0,%1"
[(set_attr "type" "fp")])
+;; This expander is here to avoid FLOAT_WORDS_BIGENDIAN tests in
+;; builtins.c and optabs.c that are not correct for IBM long double
+;; when little-endian.
+(define_expand "signbittf2"
+ [(set (match_dup 2)
+ (float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))
+ (set (match_dup 3)
+ (subreg:DI (match_dup 2) 0))
+ (set (match_dup 4)
+ (match_dup 5))
+ (set (match_operand:SI 0 "gpc_reg_operand" "")
+ (match_dup 6))]
+ "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT
+ && (TARGET_FPRS || TARGET_E500_DOUBLE)
+ && TARGET_LONG_DOUBLE_128"
+{
+ operands[2] = gen_reg_rtx (DFmode);
+ operands[3] = gen_reg_rtx (DImode);
+ if (TARGET_POWERPC64)
+ {
+ operands[4] = gen_reg_rtx (DImode);
+ operands[5] = gen_rtx_LSHIFTRT (DImode, operands[3], GEN_INT (63));
+ operands[6] = gen_rtx_SUBREG (SImode, operands[4],
+ WORDS_BIG_ENDIAN ? 4 : 0);
+ }
+ else
+ {
+ operands[4] = gen_reg_rtx (SImode);
+ operands[5] = gen_rtx_SUBREG (SImode, operands[3],
+ WORDS_BIG_ENDIAN ? 0 : 4);
+ operands[6] = gen_rtx_LSHIFTRT (SImode, operands[4], GEN_INT (31));
+ }
+})
+
(define_expand "copysign<mode>3"
[(set (match_dup 3)
(abs:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")))
@@ -9266,8 +9301,8 @@
"&& reload_completed"
[(pc)]
{
- const int lo_word = FLOAT_WORDS_BIG_ENDIAN ? GET_MODE_SIZE (DFmode) : 0;
- const int hi_word = FLOAT_WORDS_BIG_ENDIAN ? 0 : GET_MODE_SIZE (DFmode);
+ const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
+ const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
emit_move_insn (simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word),
operands[1]);
emit_move_insn (simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word),
@@ -9496,8 +9531,8 @@
&& TARGET_LONG_DOUBLE_128"
"
{
- const int hi_word = FLOAT_WORDS_BIG_ENDIAN ? 0 : GET_MODE_SIZE (DFmode);
- const int lo_word = FLOAT_WORDS_BIG_ENDIAN ? GET_MODE_SIZE (DFmode) : 0;
+ const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
+ const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
operands[3] = gen_reg_rtx (DFmode);
operands[4] = gen_reg_rtx (CCFPmode);
operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
@@ -12885,8 +12920,8 @@
(match_dup 13)]
{
REAL_VALUE_TYPE rv;
- const int lo_word = FLOAT_WORDS_BIG_ENDIAN ? GET_MODE_SIZE (DFmode) : 0;
- const int hi_word = FLOAT_WORDS_BIG_ENDIAN ? 0 : GET_MODE_SIZE (DFmode);
+ const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
+ const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
operands[5] = simplify_gen_subreg (DFmode, operands[1], TFmode, hi_word);
operands[6] = simplify_gen_subreg (DFmode, operands[1], TFmode, lo_word);
diff --git a/gcc/config/rs6000/spe.md b/gcc/config/rs6000/spe.md
index cec2b43..bf10a5d 100644
--- a/gcc/config/rs6000/spe.md
+++ b/gcc/config/rs6000/spe.md
@@ -2604,8 +2604,8 @@
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
"
{
- const int hi_word = FLOAT_WORDS_BIG_ENDIAN ? 0 : GET_MODE_SIZE (DFmode);
- const int lo_word = FLOAT_WORDS_BIG_ENDIAN ? GET_MODE_SIZE (DFmode) : 0;
+ const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
+ const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
operands[3] = gen_reg_rtx (DFmode);
operands[4] = gen_reg_rtx (CCFPmode);
operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);
@@ -2627,8 +2627,8 @@
&& TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && TARGET_LONG_DOUBLE_128"
"
{
- const int hi_word = FLOAT_WORDS_BIG_ENDIAN ? 0 : GET_MODE_SIZE (DFmode);
- const int lo_word = FLOAT_WORDS_BIG_ENDIAN ? GET_MODE_SIZE (DFmode) : 0;
+ const int hi_word = LONG_DOUBLE_LARGE_FIRST ? 0 : GET_MODE_SIZE (DFmode);
+ const int lo_word = LONG_DOUBLE_LARGE_FIRST ? GET_MODE_SIZE (DFmode) : 0;
operands[3] = gen_reg_rtx (DFmode);
operands[4] = gen_reg_rtx (CCFPmode);
operands[5] = simplify_gen_subreg (DFmode, operands[0], TFmode, hi_word);