]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
rs6000.c (output_vec_const_move): Handle little-endian code generation.
authorMaciej W. Rozycki <macro@codesourcery.com>
Mon, 7 Jul 2014 15:48:23 +0000 (15:48 +0000)
committerMaciej W. Rozycki <macro@gcc.gnu.org>
Mon, 7 Jul 2014 15:48:23 +0000 (15:48 +0000)
gcc/
* config/rs6000/rs6000.c (output_vec_const_move): Handle
little-endian code generation.
* config/rs6000/spe.md (spe_evmergehi): Rename to...
(vec_perm00_v2si): ... this.  Handle little-endian code
generation.
(spe_evmergehilo): Rename to...
(vec_perm01_v2si): ... this.  Handle little-endian code
generation.
(spe_evmergelo): Rename to...
(vec_perm11_v2si): ... this.  Handle little-endian code
generation.
(spe_evmergelohi): Rename to...
(vec_perm10_v2si): ... this.  Handle little-endian code
generation.
(spe_evmergehi, spe_evmergehilo): New expanders.
(spe_evmergelo, spe_evmergelohi): Likewise.
(*frob_<SPE64:mode>_<DITI:mode>): Handle little-endian code
generation.
(*frob_tf_ti): Likewise.
(*frob_<mode>_di_2): Likewise.
(*frob_tf_di_8_2): Likewise.
(*frob_di_<mode>): Likewise.
(*frob_ti_tf): Likewise.
(*frob_<DITI:mode>_<SPE64:mode>_2): Likewise.
(*frob_ti_<mode>_8_2): Likewise.
(*frob_ti_tf_2): Likewise.
(mov_si<mode>_e500_subreg0): Rename to...
(mov_si<mode>_e500_subreg0_be): ... this.  Restrict to the big
endianness only.
(*mov_si<mode>_e500_subreg0_le): New instruction pattern.
(*mov_si<mode>_e500_subreg0_elf_low): Rename to...
(*mov_si<mode>_e500_subreg0_elf_low_be): ... this.  Restrict to
the big endianness only.
(*mov_si<mode>_e500_subreg0_elf_low_le): New instruction pattern.
(*mov_si<mode>_e500_subreg0_2): Rename to...
(*mov_si<mode>_e500_subreg0_2_be): ... this.  Restrict to the
big big endianness only.
(*mov_si<mode>_e500_subreg0_2_le): New instruction pattern.
(*mov_si<mode>_e500_subreg4): Rename to...
(*mov_si<mode>_e500_subreg4_be): ... this.  Restrict to the big
endianness only.
(mov_si<mode>_e500_subreg4_le): New instruction pattern.
(*mov_si<mode>_e500_subreg4_elf_low): Rename to...
(*mov_si<mode>_e500_subreg4_elf_low_be): ... this.  Restrict to
the big endianness only.
(*mov_si<mode>_e500_subreg4_elf_low_le): New instruction/splitter
pattern.
(*mov_si<mode>_e500_subreg4_2): Rename to...
(*mov_si<mode>_e500_subreg4_2_be): ... this.  Restrict to the big
endianness only.
(*mov_si<mode>_e500_subreg4_2_le): New instruction pattern.
(*mov_sitf_e500_subreg8): Rename to...
(*mov_sitf_e500_subreg8_be): ... this.  Restrict to the big
endianness only.
(*mov_sitf_e500_subreg8_le): New instruction pattern.
(*mov_sitf_e500_subreg8_2): Rename to...
(*mov_sitf_e500_subreg8_2_be): ... this.  Restrict to the big
endianness only.
(*mov_sitf_e500_subreg8_2_le): New instruction pattern.
(*mov_sitf_e500_subreg12): Rename to...
(*mov_sitf_e500_subreg12_be): ... this.  Restrict to the big
endianness only.
(*mov_sitf_e500_subreg12_le): New instruction pattern.
(*mov_sitf_e500_subreg12_2): Rename to...
(*mov_sitf_e500_subreg12_2_be): ... this.  Restrict to the big
endianness only.
(*mov_sitf_e500_subreg12_2_le): New instruction pattern.

gcc/testsuite/
* gcc.target/powerpc/spe-evmerge.c: New file.

From-SVN: r212335

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/spe.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/spe-evmerge.c [new file with mode: 0644]

index 1077a658fbcc4f671d257c8d38a4a73c403cbe55..8eec9325cfbcfc700bb06f2504a8f89529df902b 100644 (file)
@@ -1,3 +1,73 @@
+2014-07-07  Maciej W. Rozycki  <macro@codesourcery.com>
+
+       * config/rs6000/rs6000.c (output_vec_const_move): Handle
+       little-endian code generation.
+       * config/rs6000/spe.md (spe_evmergehi): Rename to...
+       (vec_perm00_v2si): ... this.  Handle little-endian code 
+       generation.
+       (spe_evmergehilo): Rename to...
+       (vec_perm01_v2si): ... this.  Handle little-endian code
+       generation.
+       (spe_evmergelo): Rename to...
+       (vec_perm11_v2si): ... this.  Handle little-endian code
+       generation.
+       (spe_evmergelohi): Rename to...
+       (vec_perm10_v2si): ... this.  Handle little-endian code
+       generation.
+       (spe_evmergehi, spe_evmergehilo): New expanders.
+       (spe_evmergelo, spe_evmergelohi): Likewise.
+       (*frob_<SPE64:mode>_<DITI:mode>): Handle little-endian code
+       generation.
+       (*frob_tf_ti): Likewise.
+       (*frob_<mode>_di_2): Likewise.
+       (*frob_tf_di_8_2): Likewise.
+       (*frob_di_<mode>): Likewise.
+       (*frob_ti_tf): Likewise.
+       (*frob_<DITI:mode>_<SPE64:mode>_2): Likewise.
+       (*frob_ti_<mode>_8_2): Likewise.
+       (*frob_ti_tf_2): Likewise.
+       (mov_si<mode>_e500_subreg0): Rename to...
+       (mov_si<mode>_e500_subreg0_be): ... this.  Restrict to the big
+       endianness only.
+       (*mov_si<mode>_e500_subreg0_le): New instruction pattern.
+       (*mov_si<mode>_e500_subreg0_elf_low): Rename to...
+       (*mov_si<mode>_e500_subreg0_elf_low_be): ... this.  Restrict to 
+       the big endianness only.
+       (*mov_si<mode>_e500_subreg0_elf_low_le): New instruction pattern.
+       (*mov_si<mode>_e500_subreg0_2): Rename to...
+       (*mov_si<mode>_e500_subreg0_2_be): ... this.  Restrict to the
+       big big endianness only.
+       (*mov_si<mode>_e500_subreg0_2_le): New instruction pattern.
+       (*mov_si<mode>_e500_subreg4): Rename to...
+       (*mov_si<mode>_e500_subreg4_be): ... this.  Restrict to the big
+       endianness only.
+       (mov_si<mode>_e500_subreg4_le): New instruction pattern.
+       (*mov_si<mode>_e500_subreg4_elf_low): Rename to...
+       (*mov_si<mode>_e500_subreg4_elf_low_be): ... this.  Restrict to
+       the big endianness only.
+       (*mov_si<mode>_e500_subreg4_elf_low_le): New instruction/splitter
+       pattern.
+       (*mov_si<mode>_e500_subreg4_2): Rename to...
+       (*mov_si<mode>_e500_subreg4_2_be): ... this.  Restrict to the big
+       endianness only.
+       (*mov_si<mode>_e500_subreg4_2_le): New instruction pattern.
+       (*mov_sitf_e500_subreg8): Rename to...
+       (*mov_sitf_e500_subreg8_be): ... this.  Restrict to the big
+       endianness only.
+       (*mov_sitf_e500_subreg8_le): New instruction pattern.
+       (*mov_sitf_e500_subreg8_2): Rename to...
+       (*mov_sitf_e500_subreg8_2_be): ... this.  Restrict to the big
+       endianness only.
+       (*mov_sitf_e500_subreg8_2_le): New instruction pattern.
+       (*mov_sitf_e500_subreg12): Rename to...
+       (*mov_sitf_e500_subreg12_be): ... this.  Restrict to the big
+       endianness only.
+       (*mov_sitf_e500_subreg12_le): New instruction pattern.
+       (*mov_sitf_e500_subreg12_2): Rename to...
+       (*mov_sitf_e500_subreg12_2_be): ... this.  Restrict to the big
+       endianness only.
+       (*mov_sitf_e500_subreg12_2_le): New instruction pattern.
+
 2014-07-07  Max Ostapenko  <m.ostapenko@partner.samsung.com>
 
        * asan.c (instrument_strlen_call): Do not instrument first byte in strlen
index 215e65b70e59025a53469490e0f268ef8ac01b62..1c8c9922ed913d762babcbe5ad06798d33893b91 100644 (file)
@@ -5300,8 +5300,10 @@ output_vec_const_move (rtx *operands)
   operands[2] = CONST_VECTOR_ELT (vec, 1);
   if (cst == cst2)
     return "li %0,%1\n\tevmergelo %0,%0,%0";
-  else
+  else if (WORDS_BIG_ENDIAN)
     return "li %0,%1\n\tevmergelo %0,%0,%0\n\tli %0,%2";
+  else
+    return "li %0,%2\n\tevmergelo %0,%0,%0\n\tli %0,%1";
 }
 
 /* Initialize TARGET of vector PAIRED to VALS.  */
index ad7eaf0c34ebdda92093f0f7eff2903d472eae53..8eec7b71ed3ac84539dc1e34c7ad385716bb5a94 100644 (file)
   [(set_attr "type" "vecload")
    (set_attr  "length" "4")])
 
-(define_insn "spe_evmergehi"
+;; Integer vector permutation instructions.  The pairs of digits in the
+;; names of these instructions indicate the indices, in the memory vector
+;; element ordering, of the vector elements permuted to the output vector
+;; from the first and the second input vector respectively.
+
+(define_insn "vec_perm00_v2si"
   [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
        (vec_select:V2SI
          (vec_concat:V4SI
            (match_operand:V2SI 2 "gpc_reg_operand" "r"))
          (parallel [(const_int 0) (const_int 2)])))]
   "TARGET_SPE"
-  "evmergehi %0,%1,%2"
+{
+  if (WORDS_BIG_ENDIAN)
+    return "evmergehi %0,%1,%2";
+  else
+    return "evmergelo %0,%2,%1";
+}
   [(set_attr "type" "vecsimple")
    (set_attr  "length" "4")])
 
-(define_insn "spe_evmergehilo"
+(define_insn "vec_perm01_v2si"
   [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
        (vec_select:V2SI
          (vec_concat:V4SI
            (match_operand:V2SI 2 "gpc_reg_operand" "r"))
          (parallel [(const_int 0) (const_int 3)])))]
   "TARGET_SPE"
-  "evmergehilo %0,%1,%2"
+{
+  if (WORDS_BIG_ENDIAN)
+    return "evmergehilo %0,%1,%2";
+  else
+    return "evmergehilo %0,%2,%1";
+}
   [(set_attr "type" "vecsimple")
    (set_attr  "length" "4")])
 
-(define_insn "spe_evmergelo"
+(define_insn "vec_perm11_v2si"
   [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
        (vec_select:V2SI
          (vec_concat:V4SI
            (match_operand:V2SI 2 "gpc_reg_operand" "r"))
          (parallel [(const_int 1) (const_int 3)])))]
   "TARGET_SPE"
-  "evmergelo %0,%1,%2"
+{
+  if (WORDS_BIG_ENDIAN)
+    return "evmergelo %0,%1,%2";
+  else
+    return "evmergehi %0,%2,%1";
+}
   [(set_attr "type" "vecsimple")
    (set_attr  "length" "4")])
 
-(define_insn "spe_evmergelohi"
+(define_insn "vec_perm10_v2si"
   [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
        (vec_select:V2SI
          (vec_concat:V4SI
            (match_operand:V2SI 2 "gpc_reg_operand" "r"))
          (parallel [(const_int 1) (const_int 2)])))]
   "TARGET_SPE"
-  "evmergelohi %0,%1,%2"
+{
+  if (WORDS_BIG_ENDIAN)
+    return "evmergelohi %0,%1,%2";
+  else
+    return "evmergelohi %0,%2,%1";
+}
   [(set_attr "type" "vecsimple")
    (set_attr  "length" "4")])
 
     FAIL;
 })
 
+(define_expand "spe_evmergehi"
+  [(match_operand:V2SI 0 "register_operand" "")
+   (match_operand:V2SI 1 "register_operand" "")
+   (match_operand:V2SI 2 "register_operand" "")]
+  "TARGET_SPE"
+{
+  if (BYTES_BIG_ENDIAN)
+    emit_insn (gen_vec_perm00_v2si (operands[0], operands[1], operands[2]));
+  else
+    emit_insn (gen_vec_perm11_v2si (operands[0], operands[2], operands[1]));
+  DONE;
+})
+
+(define_expand "spe_evmergehilo"
+  [(match_operand:V2SI 0 "register_operand" "")
+   (match_operand:V2SI 1 "register_operand" "")
+   (match_operand:V2SI 2 "register_operand" "")]
+  "TARGET_SPE"
+{
+  if (BYTES_BIG_ENDIAN)
+    emit_insn (gen_vec_perm01_v2si (operands[0], operands[1], operands[2]));
+  else
+    emit_insn (gen_vec_perm01_v2si (operands[0], operands[2], operands[1]));
+  DONE;
+})
+
+(define_expand "spe_evmergelo"
+  [(match_operand:V2SI 0 "register_operand" "")
+   (match_operand:V2SI 1 "register_operand" "")
+   (match_operand:V2SI 2 "register_operand" "")]
+  "TARGET_SPE"
+{
+  if (BYTES_BIG_ENDIAN)
+    emit_insn (gen_vec_perm11_v2si (operands[0], operands[1], operands[2]));
+  else
+    emit_insn (gen_vec_perm00_v2si (operands[0], operands[2], operands[1]));
+  DONE;
+})
+
+(define_expand "spe_evmergelohi"
+  [(match_operand:V2SI 0 "register_operand" "")
+   (match_operand:V2SI 1 "register_operand" "")
+   (match_operand:V2SI 2 "register_operand" "")]
+  "TARGET_SPE"
+{
+  if (BYTES_BIG_ENDIAN)
+    emit_insn (gen_vec_perm10_v2si (operands[0], operands[1], operands[2]));
+  else
+    emit_insn (gen_vec_perm10_v2si (operands[0], operands[2], operands[1]));
+  DONE;
+})
+
+;; End of integer vector permutation instructions.
+
 (define_insn "spe_evnand"
   [(set (match_operand:V2SI 0 "gpc_reg_operand" "=r")
         (not:V2SI (and:V2SI (match_operand:V2SI 1 "gpc_reg_operand" "r")
         (subreg:SPE64 (match_operand:DITI 1 "input_operand" "r,m") 0))]
   "(TARGET_E500_DOUBLE && <SPE64:MODE>mode == DFmode)
    || (TARGET_SPE && <SPE64:MODE>mode != DFmode)"
-  "@
-   evmergelo %0,%1,%L1
-   evldd%X1 %0,%y1")
+{
+  switch (which_alternative)
+    {
+    default:
+      gcc_unreachable ();
+    case 0:
+      if (WORDS_BIG_ENDIAN)
+       return "evmergelo %0,%1,%L1";
+      else
+       return "evmergelo %0,%L1,%1";
+    case 1:
+      return "evldd%X1 %0,%y1";
+    }
+})
 
 (define_insn "*frob_tf_ti"
   [(set (match_operand:TF 0 "gpc_reg_operand" "=r")
         (subreg:TF (match_operand:TI 1 "gpc_reg_operand" "r") 0))]
   "TARGET_E500_DOUBLE"
-  "evmergelo %0,%1,%L1\;evmergelo %L0,%Y1,%Z1"
+{
+  if (WORDS_BIG_ENDIAN)
+    return "evmergelo %0,%1,%L1\;evmergelo %L0,%Y1,%Z1";
+  else
+    return "evmergelo %L0,%Z1,%Y1\;evmergelo %0,%L1,%1";
+}
   [(set_attr "length" "8")])
 
 (define_insn "*frob_<mode>_di_2"
         (match_operand:DI 1 "input_operand" "r,m"))]
   "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
    || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)"
-  "@
-   evmergelo %0,%1,%L1
-   evldd%X1 %0,%y1")
+{
+  switch (which_alternative)
+    {
+    default:
+      gcc_unreachable ();
+    case 0:
+      if (WORDS_BIG_ENDIAN)
+       return "evmergelo %0,%1,%L1";
+      else
+       return "evmergelo %0,%L1,%1";
+    case 1:
+      return "evldd%X1 %0,%y1";
+    }
+})
 
 (define_insn "*frob_tf_di_8_2"
   [(set (subreg:DI (match_operand:TF 0 "nonimmediate_operand" "+&r,r") 8)
         (match_operand:DI 1 "input_operand" "r,m"))]
   "TARGET_E500_DOUBLE"
-  "@
-   evmergelo %L0,%1,%L1
-   evldd%X1 %L0,%y1")
+{
+  switch (which_alternative)
+    {
+    default:
+      gcc_unreachable ();
+    case 0:
+      if (WORDS_BIG_ENDIAN)
+       return "evmergelo %L0,%1,%L1";
+      else
+       return "evmergelo %L0,%L1,%1";
+    case 1:
+      return "evldd%X1 %L0,%y1";
+    }
+})
 
 (define_insn "*frob_di_<mode>"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=&r")
         (subreg:DI (match_operand:SPE64TF 1 "input_operand" "r") 0))]
   "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
    || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)"
-  "evmergehi %0,%1,%1\;mr %L0,%1"
+{
+  if (WORDS_BIG_ENDIAN)
+    return "evmergehi %0,%1,%1\;mr %L0,%1";
+  else
+    return "evmergehi %L0,%1,%1\;mr %0,%1";
+}
   [(set_attr "length" "8")])
 
 (define_insn "*frob_ti_tf"
   [(set (match_operand:TI 0 "nonimmediate_operand" "=&r")
         (subreg:TI (match_operand:TF 1 "input_operand" "r") 0))]
   "TARGET_E500_DOUBLE"
-  "evmergehi %0,%1,%1\;mr %L0,%1\;evmergehi %Y0,%L1,%L1\;mr %Z0,%L1"
+{
+  if (WORDS_BIG_ENDIAN)
+    return "evmergehi %0,%1,%1\;mr %L0,%1\;evmergehi %Y0,%L1,%L1\;mr %Z0,%L1";
+  else
+    return "evmergehi %Z0,%L1,%L1\;mr %Y0,%L1\;evmergehi %L0,%1,%1\;mr %0,%1";
+}
   [(set_attr "length" "16")])
 
 (define_insn "*frob_<DITI:mode>_<SPE64:mode>_2"
     default: 
       gcc_unreachable ();
     case 0:
-      return \"evmergehi %0,%1,%1\;mr %L0,%1\";
+      if (WORDS_BIG_ENDIAN)
+       return \"evmergehi %0,%1,%1\;mr %L0,%1\";
+      else
+       return \"evmergehi %L0,%1,%1\;mr %0,%1\";
     case 1:
       /* If the address is not offsettable we need to load the whole
         doubleword into a 64-bit register and then copy the high word
         to form the correct output layout.  */
       if (!offsettable_nonstrict_memref_p (operands[1]))
-       return \"evldd%X1 %L0,%y1\;evmergehi %0,%L0,%L0\";
+       {
+         if (WORDS_BIG_ENDIAN)
+           return \"evldd%X1 %L0,%y1\;evmergehi %0,%L0,%L0\";
+         else
+           return \"evldd%X1 %0,%y1\;evmergehi %L0,%0,%0\";
+       }
       /* If the low-address word is used in the address, we must load
        it last.  Otherwise, load it first.  Note that we cannot have
        auto-increment in that case since the address register is
        known to be dead.  */
       if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
                             operands[1], 0))
-       return \"lwz %L0,%L1\;lwz %0,%1\";
+       {
+         if (WORDS_BIG_ENDIAN)
+           return \"lwz %L0,%L1\;lwz %0,%1\";
+         else
+           return \"lwz %0,%1\;lwz %L0,%L1\";
+       }
       else
-        return \"lwz%U1%X1 %0,%1\;lwz %L0,%L1\";
+       {
+         if (WORDS_BIG_ENDIAN)
+           return \"lwz%U1%X1 %0,%1\;lwz %L0,%L1\";
+         else
+           return \"lwz%U1%X1 %L0,%L1\;lwz %0,%1\";
+       }
     }
 }"
   [(set_attr "length" "8,8")])
     default: 
       gcc_unreachable ();
     case 0:
-      return \"evmergehi %Y0,%1,%1\;mr %Z0,%1\";
+      if (WORDS_BIG_ENDIAN)
+       return \"evmergehi %Y0,%1,%1\;mr %Z0,%1\";
+      else
+       return \"evmergehi %Z0,%1,%1\;mr %Y0,%1\";
     case 1:
       if (!offsettable_nonstrict_memref_p (operands[1]))
-       return \"evldd%X1 %Z0,%y1\;evmergehi %Y0,%Z0,%Z0\";
+       {
+         if (WORDS_BIG_ENDIAN)
+           return \"evldd%X1 %Z0,%y1\;evmergehi %Y0,%Z0,%Z0\";
+         else
+           return \"evldd%X1 %Y0,%y1\;evmergehi %Z0,%Y0,%Y0\";
+       }
       if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
                             operands[1], 0))
-       return \"lwz %Z0,%L1\;lwz %Y0,%1\";
+       {
+         if (WORDS_BIG_ENDIAN)
+           return \"lwz %Z0,%L1\;lwz %Y0,%1\";
+         else
+           return \"lwz %Y0,%1\;lwz %Z0,%L1\";
+       }
       else
-        return \"lwz%U1%X1 %Y0,%1\;lwz %Z0,%L1\";
+       {
+         if (WORDS_BIG_ENDIAN)
+           return \"lwz%U1%X1 %Y0,%1\;lwz %Z0,%L1\";
+         else
+           return \"lwz%U1%X1 %Z0,%L1\;lwz %Y0,%1\";
+       }
     }
 }"
   [(set_attr "length" "8,8")])
   [(set (subreg:TF (match_operand:TI 0 "gpc_reg_operand" "=&r") 0)
        (match_operand:TF 1 "input_operand" "r"))]
   "TARGET_E500_DOUBLE"
-  "evmergehi %0,%1,%1\;mr %L0,%1\;evmergehi %Y0,%L1,%L1\;mr %Z0,%L1"
+{
+  if (WORDS_BIG_ENDIAN)
+    return "evmergehi %0,%1,%1\;mr %L0,%1\;evmergehi %Y0,%L1,%L1\;mr %Z0,%L1";
+  else
+    return "evmergehi %Z0,%L1,%L1\;mr %Y0,%L1\;evmergehi %L0,%1,%1\;mr %0,%1";
+}
   [(set_attr "length" "16")])
 
-(define_insn "mov_si<mode>_e500_subreg0"
+(define_insn "mov_si<mode>_e500_subreg0_be"
   [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r,&r") 0)
        (match_operand:SI 1 "input_operand" "r,m"))]
-  "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
-   || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)"
+  "WORDS_BIG_ENDIAN
+   && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
+       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))"
   "@
    evmergelo %0,%1,%0
    evmergelohi %0,%0,%0\;lwz%U1%X1 %0,%1\;evmergelohi %0,%0,%0"
   [(set_attr "length" "4,12")])
 
-(define_insn_and_split "*mov_si<mode>_e500_subreg0_elf_low"
+(define_insn "*mov_si<mode>_e500_subreg0_le"
+  [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r,r") 0)
+       (match_operand:SI 1 "input_operand" "r,m"))]
+  "!WORDS_BIG_ENDIAN
+   && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
+       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))"
+  "@
+   mr %0,%1
+   lwz%U1%X1 %0,%1")
+
+(define_insn_and_split "*mov_si<mode>_e500_subreg0_elf_low_be"
   [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 0)
        (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                   (match_operand 2 "" "")))]
-  "((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
-    || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))
-   && TARGET_ELF && !TARGET_64BIT && can_create_pseudo_p ()"
+  "WORDS_BIG_ENDIAN
+   && (((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
+       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))
+       && TARGET_ELF && !TARGET_64BIT && can_create_pseudo_p ())"
   "#"
   "&& 1"
   [(pc)]
 {
   rtx tmp = gen_reg_rtx (SImode);
   emit_insn (gen_elf_low (tmp, operands[1], operands[2]));
-  emit_insn (gen_mov_si<mode>_e500_subreg0 (operands[0], tmp));
+  emit_insn (gen_mov_si<mode>_e500_subreg0_be (operands[0], tmp));
   DONE;
 }
   [(set_attr "length" "8")])
 
+(define_insn "*mov_si<mode>_e500_subreg0_elf_low_le"
+  [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 0)
+       (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+                  (match_operand 2 "" "")))]
+  "!WORDS_BIG_ENDIAN
+   && (((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
+       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))
+       && TARGET_ELF && !TARGET_64BIT)"
+  "addic %0,%1,%K2")
+
 ;; ??? Could use evstwwe for memory stores in some cases, depending on
 ;; the offset.
-(define_insn "*mov_si<mode>_e500_subreg0_2"
+(define_insn "*mov_si<mode>_e500_subreg0_2_be"
   [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
        (subreg:SI (match_operand:SPE64TF 1 "register_operand" "+r,&r") 0))]
-  "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
-   || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)"
+  "WORDS_BIG_ENDIAN
+   && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
+       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))"
   "@
    evmergehi %0,%0,%1
    evmergelohi %1,%1,%1\;stw%U0%X0 %1,%0"
   [(set_attr "length" "4,8")])
 
-(define_insn "*mov_si<mode>_e500_subreg4"
+(define_insn "*mov_si<mode>_e500_subreg0_2_le"
+  [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
+       (subreg:SI (match_operand:SPE64TF 1 "register_operand" "+r,r") 0))]
+  "!WORDS_BIG_ENDIAN
+   && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
+       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))"
+  "@
+   mr %0,%1
+   stw%U0%X0 %1,%0")
+
+(define_insn "*mov_si<mode>_e500_subreg4_be"
   [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r,r") 4)
        (match_operand:SI 1 "input_operand" "r,m"))]
-  "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
-   || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)"
+  "WORDS_BIG_ENDIAN
+   && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
+       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))"
   "@
    mr %0,%1
    lwz%U1%X1 %0,%1")
 
-(define_insn "*mov_si<mode>_e500_subreg4_elf_low"
+(define_insn "mov_si<mode>_e500_subreg4_le"
+  [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r,&r") 4)
+       (match_operand:SI 1 "input_operand" "r,m"))]
+  "!WORDS_BIG_ENDIAN
+   && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
+       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))"
+  "@
+   evmergelo %0,%1,%0
+   evmergelohi %0,%0,%0\;lwz%U1%X1 %0,%1\;evmergelohi %0,%0,%0"
+  [(set_attr "length" "4,12")])
+
+(define_insn "*mov_si<mode>_e500_subreg4_elf_low_be"
   [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 4)
        (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r")
                   (match_operand 2 "" "")))]
-  "((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
-    || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))
-   && TARGET_ELF && !TARGET_64BIT"
+  "WORDS_BIG_ENDIAN
+   && (((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
+       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))
+       && TARGET_ELF && !TARGET_64BIT)"
   "addic %0,%1,%K2")
 
-(define_insn "*mov_si<mode>_e500_subreg4_2"
+(define_insn_and_split "*mov_si<mode>_e500_subreg4_elf_low_le"
+  [(set (subreg:SI (match_operand:SPE64TF 0 "register_operand" "+r") 4)
+       (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+                  (match_operand 2 "" "")))]
+  "!WORDS_BIG_ENDIAN
+   && (((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
+       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))
+       && TARGET_ELF && !TARGET_64BIT && can_create_pseudo_p ())"
+  "#"
+  "&& 1"
+  [(pc)]
+{
+  rtx tmp = gen_reg_rtx (SImode);
+  emit_insn (gen_elf_low (tmp, operands[1], operands[2]));
+  emit_insn (gen_mov_si<mode>_e500_subreg4_le (operands[0], tmp));
+  DONE;
+}
+  [(set_attr "length" "8")])
+
+(define_insn "*mov_si<mode>_e500_subreg4_2_be"
   [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
        (subreg:SI (match_operand:SPE64TF 1 "register_operand" "r,r") 4))]
-  "(TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
-   || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode)"
+  "WORDS_BIG_ENDIAN
+   && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
+       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))"
   "@
    mr %0,%1
    stw%U0%X0 %1,%0")
 
-(define_insn "*mov_sitf_e500_subreg8"
+(define_insn "*mov_si<mode>_e500_subreg4_2_le"
+  [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
+       (subreg:SI (match_operand:SPE64TF 1 "register_operand" "+r,&r") 4))]
+  "!WORDS_BIG_ENDIAN
+   && ((TARGET_E500_DOUBLE && (<MODE>mode == DFmode || <MODE>mode == TFmode))
+       || (TARGET_SPE && <MODE>mode != DFmode && <MODE>mode != TFmode))"
+  "@
+   evmergehi %0,%0,%1
+   evmergelohi %1,%1,%1\;stw%U0%X0 %1,%0"
+  [(set_attr "length" "4,8")])
+
+(define_insn "*mov_sitf_e500_subreg8_be"
   [(set (subreg:SI (match_operand:TF 0 "register_operand" "+r,&r") 8)
        (match_operand:SI 1 "input_operand" "r,m"))]
-  "TARGET_E500_DOUBLE"
+  "WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE"
   "@
    evmergelo %L0,%1,%L0
    evmergelohi %L0,%L0,%L0\;lwz%U1%X1 %L0,%1\;evmergelohi %L0,%L0,%L0"
   [(set_attr "length" "4,12")])
 
-(define_insn "*mov_sitf_e500_subreg8_2"
+(define_insn "*mov_sitf_e500_subreg8_le"
+  [(set (subreg:SI (match_operand:TF 0 "register_operand" "+r,r") 8)
+       (match_operand:SI 1 "input_operand" "r,m"))]
+  "!WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE"
+  "@
+   mr %L0,%1
+   lwz%U1%X1 %L0,%1")
+
+(define_insn "*mov_sitf_e500_subreg8_2_be"
   [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
        (subreg:SI (match_operand:TF 1 "register_operand" "+r,&r") 8))]
-  "TARGET_E500_DOUBLE"
+  "WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE"
   "@
    evmergehi %0,%0,%L1
    evmergelohi %L1,%L1,%L1\;stw%U0%X0 %L1,%0"
   [(set_attr "length" "4,8")])
 
-(define_insn "*mov_sitf_e500_subreg12"
+(define_insn "*mov_sitf_e500_subreg8_2_le"
+  [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
+       (subreg:SI (match_operand:TF 1 "register_operand" "r,r") 8))]
+  "!WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE"
+  "@
+   mr %0,%L1
+   stw%U0%X0 %L1,%0")
+
+(define_insn "*mov_sitf_e500_subreg12_be"
   [(set (subreg:SI (match_operand:TF 0 "register_operand" "+r,r") 12)
        (match_operand:SI 1 "input_operand" "r,m"))]
-  "TARGET_E500_DOUBLE"
+  "WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE"
   "@
    mr %L0,%1
    lwz%U1%X1 %L0,%1")
 
-(define_insn "*mov_sitf_e500_subreg12_2"
+(define_insn "*mov_sitf_e500_subreg12_le"
+  [(set (subreg:SI (match_operand:TF 0 "register_operand" "+r,&r") 12)
+       (match_operand:SI 1 "input_operand" "r,m"))]
+  "!WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE"
+  "@
+   evmergelo %L0,%1,%L0
+   evmergelohi %L0,%L0,%L0\;lwz%U1%X1 %L0,%1\;evmergelohi %L0,%L0,%L0"
+  [(set_attr "length" "4,12")])
+
+(define_insn "*mov_sitf_e500_subreg12_2_be"
   [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
        (subreg:SI (match_operand:TF 1 "register_operand" "r,r") 12))]
-  "TARGET_E500_DOUBLE"
+  "WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE"
   "@
    mr %0,%L1
    stw%U0%X0 %L1,%0")
 
+(define_insn "*mov_sitf_e500_subreg12_2_le"
+  [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
+       (subreg:SI (match_operand:TF 1 "register_operand" "+r,&r") 12))]
+  "!WORDS_BIG_ENDIAN && TARGET_E500_DOUBLE"
+  "@
+   evmergehi %0,%0,%L1
+   evmergelohi %L1,%L1,%L1\;stw%U0%X0 %L1,%0"
+  [(set_attr "length" "4,8")])
+
 ;; FIXME: Allow r=CONST0.
 (define_insn "*movdf_e500_double"
   [(set (match_operand:DF 0 "rs6000_nonimmediate_operand" "=r,r,m")
index bc23150d66a4e50c42e5fd6e42c35eca009cd2f9..62b13fcf5f495b562ef66e25eabe6d2fa20f9a17 100644 (file)
@@ -1,3 +1,7 @@
+2014-07-07  Maciej W. Rozycki  <macro@codesourcery.com>
+
+       * gcc.target/powerpc/spe-evmerge.c: New file.
+
 2014-07-07  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * g++.dg/cpp0x/override1.C: Tweak expected error messages.
diff --git a/gcc/testsuite/gcc.target/powerpc/spe-evmerge.c b/gcc/testsuite/gcc.target/powerpc/spe-evmerge.c
new file mode 100644 (file)
index 0000000..df0a33e
--- /dev/null
@@ -0,0 +1,71 @@
+/* Verify SPE vector permute builtins.  */
+/* { dg-do run { target { powerpc*-*-* && powerpc_spe } } } */
+/* Remove `-ansi' from options so that <spe.h> compiles.  */
+/* { dg-options "" } */
+
+#include <spe.h>
+#include <stdlib.h>
+
+#define vector __attribute__ ((vector_size (8)))
+
+#define WORDS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+
+int
+main (void)
+{
+  vector int a = { 0x11111111, 0x22222222 };
+  vector int b = { 0x33333333, 0x44444444 };
+  vector int c;
+
+  /* c[hi] = a[hi], c[lo] = b[hi]  */
+  c = __ev_mergehi (a, b);
+  if (c[0] != (WORDS_BIG_ENDIAN ? 0x11111111 : 0x44444444))
+    abort ();
+  if (c[1] != (WORDS_BIG_ENDIAN ? 0x33333333 : 0x22222222))
+    abort ();
+  /* c[hi] = a[lo], c[lo] = b[lo]  */
+  c = __ev_mergelo (a, b);
+  if (c[0] != (WORDS_BIG_ENDIAN ? 0x22222222 : 0x33333333))
+    abort ();
+  if (c[1] != (WORDS_BIG_ENDIAN ? 0x44444444 : 0x11111111))
+    abort ();
+  /* c[hi] = a[lo], c[lo] = b[hi]  */
+  c = __ev_mergelohi (a, b);
+  if (c[0] != (WORDS_BIG_ENDIAN ? 0x22222222 : 0x44444444))
+    abort ();
+  if (c[1] != (WORDS_BIG_ENDIAN ? 0x33333333 : 0x11111111))
+    abort ();
+  /* c[hi] = a[hi], c[lo] = b[lo]  */
+  c = __ev_mergehilo (a, b);
+  if (c[0] != (WORDS_BIG_ENDIAN ? 0x11111111 : 0x33333333))
+    abort ();
+  if (c[1] != (WORDS_BIG_ENDIAN ? 0x44444444 : 0x22222222))
+    abort ();
+
+  /* c[hi] = a[hi], c[lo] = b[hi]  */
+  c = __builtin_spe_evmergehi (a, b);
+  if (c[0] != (WORDS_BIG_ENDIAN ? 0x11111111 : 0x44444444))
+    abort ();
+  if (c[1] != (WORDS_BIG_ENDIAN ? 0x33333333 : 0x22222222))
+    abort ();
+  /* c[hi] = a[lo], c[lo] = b[lo]  */
+  c = __builtin_spe_evmergelo (a, b);
+  if (c[0] != (WORDS_BIG_ENDIAN ? 0x22222222 : 0x33333333))
+    abort ();
+  if (c[1] != (WORDS_BIG_ENDIAN ? 0x44444444 : 0x11111111))
+    abort ();
+  /* c[hi] = a[lo], c[lo] = b[hi]  */
+  c = __builtin_spe_evmergelohi (a, b);
+  if (c[0] != (WORDS_BIG_ENDIAN ? 0x22222222 : 0x44444444))
+    abort ();
+  if (c[1] != (WORDS_BIG_ENDIAN ? 0x33333333 : 0x11111111))
+    abort ();
+  /* c[hi] = a[hi], c[lo] = b[lo]  */
+  c = __builtin_spe_evmergehilo (a, b);
+  if (c[0] != (WORDS_BIG_ENDIAN ? 0x11111111 : 0x33333333))
+    abort ();
+  if (c[1] != (WORDS_BIG_ENDIAN ? 0x44444444 : 0x22222222))
+    abort ();
+
+  return 0;
+}