Support for PowerPC 750CL paired-single instructions
authorDavid Edelsohn <edelsohn@gnu.org>
Fri, 31 Aug 2007 05:26:38 +0000 (05:26 +0000)
committerRevital Eres <revitale@gcc.gnu.org>
Fri, 31 Aug 2007 05:26:38 +0000 (05:26 +0000)
Co-Authored-By: Revital Eres <eres@il.ibm.com>
From-SVN: r127954

20 files changed:
gcc/ChangeLog
gcc/config.gcc
gcc/config/rs6000/750cl.h [new file with mode: 0644]
gcc/config/rs6000/paired.h [new file with mode: 0644]
gcc/config/rs6000/paired.md [new file with mode: 0644]
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/rs6000.opt
gcc/config/rs6000/spe.md
gcc/doc/invoke.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/powerpc/paired-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/paired-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/paired-3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/paired-4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/paired-5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/paired-6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/paired-7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/ppc-paired.c [new file with mode: 0644]

index 99766dca08169588faf16fd20317f6fd5dae95c3..483728dd3e64cf4a3ea1d82ce0db256b31c090f8 100644 (file)
@@ -1,3 +1,39 @@
+2007-08-31  David Edelsohn  <edelsohn@gnu.org>
+            Revital Eres  <eres@il.ibm.com>
+
+        * doc/invoke.texi (-mpaired): Document flag.
+        * config.gcc: Include paired.h in powerpc extra_headers and
+        750cl.h in powerpc-*-linux*paired*.
+        * config/rs6000/rs6000.opt (-mpaired): New flag.
+        * config/rs6000/rs6000.c (paired_init_builtins,
+        paired_expand_builtin, paired_expand_lv_builtin,
+        paired_expand_stv_builtin, paired_expand_predicate_builtin):
+        New functions to support the paired single builtin functions.
+        (rs6000_hard_regno_mode_ok): Handle PAIRED_VECTOR_MODE.
+        (def_builtin, bdesc_3arg, bdesc_2arg, bdesc_1arg): Add paired
+        single builtins.
+        (bdesc_paired_preds): New structure for paired predicate
+        instructions.
+        (rs6000_expand_builtin): Expand paired single builtins.
+        (rs6000_init_builtins): Init paired single builtins.
+        (rs6000_common_init_builtins): Add v2sf_ftype_v2sf_v2sf_v2sf.
+        Rename v2sf_ftype_v2sf_v2sf to v2sf_ftype_v2sf_v2sf_spe
+        and v2sf_ftype_v2sf_spe to v2sf_ftype_v2sf.  Add new types
+        v2sf_ftype_v2sf_v2sf and v2sf_ftype_v2sf.
+        (rs6000_vector_mode_supported_p): Support paired vector mode.
+        * config/rs6000/rs6000.h: (UNITS_PER_PAIRED_WORD,
+        PAIRED_VECTOR_MODE, PAIRED_SIMD_REGNO_P, TARGET_PAIRED_FLOAT):
+        New.
+        (LOCAL_ALIGNMENT): Handle PAIRED_VECTOR_MODE.
+        (DATA_ALIGNMENT): Likewise.
+        (UNITS_PER_SIMD_WORD): Handle PAIRED_VECTOR_MODE.
+        (rs6000_builtins): Add PAIRED builtins.
+        * config/rs6000/rs6000.md: Include paired.md.
+        * config/rs6000/paired.h: New.
+        * config/rs6000/paired.md: New.
+        * config/rs6000/750cl.h: New.
+        * config/rs6000/spe.md: Recognize movv2sf instruction for 750cl.
+
 2007-08-30  Ollie Wild  <aaw@google.com>
 
        * c-opts.c (c_common_handle_option): Support -fno-directives-only.
index 6665eb70370f66565a5e24ab3b2aa332f66825af..9f6c0262cb9122098fd19cf04f091004b92bd46f 100644 (file)
@@ -312,7 +312,7 @@ mips*-*-*)
        ;;
 powerpc*-*-*)
        cpu_type=rs6000
-       extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h"
+       extra_headers="ppc-asm.h altivec.h spe.h ppu_intrinsics.h paired.h"
        need_64bit_hwint=yes
        case x$with_cpu in
            xpowerpc64|xdefault64|x6[23]0|x970|xG5|xpower[3456]|xpower6x|xrs64a)
@@ -1936,6 +1936,11 @@ powerpc-*-linux*spe*)
        extra_options="${extra_options} rs6000/sysv4.opt"
        tmake_file="rs6000/t-fprules rs6000/t-fprules-softfp soft-fp/t-softfp rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm"
        ;;
+powerpc-*-linux*paired*)
+        tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h rs6000/linux.h rs6000/750cl.h"
+        extra_options="${extra_options} rs6000/sysv4.opt"
+        tmake_file="rs6000/t-fprules rs6000/t-fprules-softfp soft-fp/t-softfp rs6000/t-ppcos ${tmake_file} rs6000/t-ppccomm"
+        ;;
 powerpc-*-linux*)
        tm_file="${tm_file} dbxelf.h elfos.h svr4.h freebsd-spec.h rs6000/sysv4.h"
        extra_options="${extra_options} rs6000/sysv4.opt"
diff --git a/gcc/config/rs6000/750cl.h b/gcc/config/rs6000/750cl.h
new file mode 100644 (file)
index 0000000..d01761b
--- /dev/null
@@ -0,0 +1,23 @@
+/* Enable 750cl paired single support.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+   Contributed by Revital Eres (eres@il.ibm.com)
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 2, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING.  If not, write to the
+   Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+#undef TARGET_PAIRED_FLOAT
+#define TARGET_PAIRED_FLOAT rs6000_paired_float
+
diff --git a/gcc/config/rs6000/paired.h b/gcc/config/rs6000/paired.h
new file mode 100644 (file)
index 0000000..e70d0fa
--- /dev/null
@@ -0,0 +1,77 @@
+/* PowerPC 750CL user include file.
+   Copyright (C) 2007 Free Software Foundation, Inc. 
+   Contributed by Revital Eres (eres@il.ibm.com).
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 2, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING.  If not, write to the
+   Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+   MA 02110-1301, USA.  */
+
+/* As a special exception, if you include this header file into source
+   files compiled by GCC, this header file does not by itself cause
+   the resulting executable to be covered by the GNU General Public
+   License.  This exception does not however invalidate any other
+   reasons why the executable file might be covered by the GNU General
+   Public License.  */
+
+#ifndef _PAIRED_H
+#define _PAIRED_H
+
+#define vector __attribute__((vector_size(8)))
+
+#define paired_msub __builtin_paired_msub
+#define paired_madd __builtin_paired_madd
+#define paired_nmsub __builtin_paired_nmsub
+#define paired_nmadd __builtin_paired_nmadd
+#define paired_sum0 __builtin_paired_sum0
+#define paired_sum1 __builtin_paired_sum1
+#define paired_div __builtin_paired_divv2sf3
+#define paired_add __builtin_paired_addv2sf3
+#define paired_sub __builtin_paired_subv2sf3
+#define paired_mul __builtin_paired_mulv2sf3
+#define paired_muls0 __builtin_paired_muls0
+#define paired_muls1 __builtin_paired_muls1
+#define paired_madds0 __builtin_paired_madds0
+#define paired_madds1 __builtin_paired_madds1
+#define paired_merge00 __builtin_paired_merge00
+#define paired_merge01 __builtin_paired_merge01
+#define paired_merge10 __builtin_paired_merge10
+#define paired_merge11 __builtin_paired_merge11
+#define paired_abs __builtin_paired_absv2sf2
+#define paired_nabs __builtin_paired_nabsv2sf2
+#define paired_neg __builtin_paired_negv2sf2
+#define paired_sqrt __builtin_paired_sqrtv2sf2
+#define paired_res __builtin_paired_resv2sf2
+#define paired_stx __builtin_paired_stx
+#define paired_lx __builtin_paired_lx
+#define paired_cmpu0 __builtin_paired_cmpu0
+#define paired_cmpu1 __builtin_paired_cmpu1
+
+/* Condition register codes for Paired predicates. */
+#define LT            0
+#define GT            1
+#define EQ            2
+#define UN            3
+
+#define paired_cmpu0_un(a,b) __builtin_paired_cmpu0 (UN, (a), (b))
+#define paired_cmpu0_eq(a,b) __builtin_paired_cmpu0 (EQ, (a), (b))
+#define paired_cmpu0_lt(a,b) __builtin_paired_cmpu0 (LT, (a), (b))
+#define paired_cmpu0_gt(a,b) __builtin_paired_cmpu0 (GT, (a), (b))
+#define paired_cmpu1_un(a,b) __builtin_paired_cmpu1 (UN, (a), (b))
+#define paired_cmpu1_eq(a,b) __builtin_paired_cmpu1 (EQ, (a), (b))
+#define paired_cmpu1_lt(a,b) __builtin_paired_cmpu1 (LT, (a), (b))
+#define paired_cmpu1_gt(a,b) __builtin_paired_cmpu1 (GT, (a), (b))
+
+#endif /* _PAIRED_H */
diff --git a/gcc/config/rs6000/paired.md b/gcc/config/rs6000/paired.md
new file mode 100644 (file)
index 0000000..ad3001d
--- /dev/null
@@ -0,0 +1,355 @@
+;; PowerPC paired single and double hummer description
+;; Copyright (C) 2007
+;; Free Software Foundation, Inc.
+;; Contributed by David Edelsohn <edelsohn@gnu.org> and Revital Eres
+;; <eres@il.ibm.com>
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING.  If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+
+(define_insn "negv2sf2"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (neg:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_neg %0,%1"
+  [(set_attr "type" "fp")])
+
+(define_insn "sqrtv2sf2"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (sqrt:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_rsqrte %0,%1"
+  [(set_attr "type" "fp")])
+
+(define_insn "absv2sf2"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (abs:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_abs %0,%1"
+  [(set_attr "type" "fp")])
+
+(define_insn "nabsv2sf2"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (neg:V2SF (abs:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f"))))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_nabs %0,%1"
+  [(set_attr "type" "fp")])
+
+(define_insn "addv2sf3"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (plus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f")
+                  (match_operand:V2SF 2 "gpc_reg_operand" "f")))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_add %0,%1,%2"
+  [(set_attr "type" "fp")])
+
+(define_insn "subv2sf3"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+        (minus:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                    (match_operand:V2SF 2 "gpc_reg_operand" "f")))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_sub %0,%1,%2"
+  [(set_attr "type" "fp")])
+
+(define_insn "mulv2sf3"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f")
+                  (match_operand:V2SF 2 "gpc_reg_operand" "f")))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_mul %0,%1,%2"
+  [(set_attr "type" "fp")])
+
+(define_insn "resv2sf2"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (unspec:V2SF [(match_operand:V2SF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
+  "TARGET_PAIRED_FLOAT && flag_finite_math_only"
+  "ps_res %0,%1"
+  [(set_attr "type" "fp")])
+
+(define_insn "divv2sf3"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (div:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                 (match_operand:V2SF 2 "gpc_reg_operand" "f")))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_div %0,%1,%2"
+  [(set_attr "type" "sdiv")])
+
+(define_insn "paired_madds0"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+                 (vec_concat:V2SF
+                 (plus:SF (mult:SF (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                                                 (parallel [(const_int 0)]))
+                                  (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
+                                         (parallel [(const_int 0)])))
+                         (vec_select:SF (match_operand:V2SF 3 "gpc_reg_operand" "f")
+                                         (parallel [(const_int 0)])))
+                (plus:SF (mult:SF (vec_select:SF (match_dup 1)
+                                         (parallel [(const_int 1)]))
+                                    (vec_select:SF (match_dup 2)
+                                         (parallel [(const_int 0)])))
+                         (vec_select:SF (match_dup 3)
+                                         (parallel [(const_int 1)])))))]
+  "TARGET_PAIRED_FLOAT && TARGET_FUSED_MADD"
+  "ps_madds0 %0,%1,%2,%3"
+  [(set_attr "type" "fp")])
+
+(define_insn "paired_madds1"
+ [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+                 (vec_concat:V2SF
+                 (plus:SF (mult:SF (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                                                  (parallel [(const_int 0)]))
+                                   (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
+                                         (parallel [(const_int 1)])))
+                          (vec_select:SF (match_operand:V2SF 3 "gpc_reg_operand" "f")
+                                         (parallel [(const_int 0)])))
+                 (plus:SF (mult:SF (vec_select:SF (match_dup 1)
+                                         (parallel [(const_int 1)]))
+                                     (vec_select:SF (match_dup 2)
+                                         (parallel [(const_int 1)])))
+                          (vec_select:SF (match_dup 3)
+                                         (parallel [(const_int 1)])))))]
+  "TARGET_PAIRED_FLOAT && TARGET_FUSED_MADD"
+  "ps_madds1 %0,%1,%2,%3"
+  [(set_attr "type" "fp")])
+
+(define_insn "paired_madd"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (plus:V2SF (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f")
+                             (match_operand:V2SF 2 "gpc_reg_operand" "f"))
+                  (match_operand:V2SF 3 "gpc_reg_operand" "f")))]
+  "TARGET_PAIRED_FLOAT && TARGET_FUSED_MADD"
+  "ps_madd %0,%1,%2,%3"
+  [(set_attr "type" "fp")]) 
+
+(define_insn "paired_msub"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (minus:V2SF (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f")
+                              (match_operand:V2SF 2 "gpc_reg_operand" "f"))
+                   (match_operand:V2SF 3 "gpc_reg_operand" "f")))]
+  "TARGET_PAIRED_FLOAT && TARGET_FUSED_MADD"
+  "ps_msub %0,%1,%2,%3"
+  [(set_attr "type" "fp")])
+
+(define_insn "paired_nmadd"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (neg:V2SF (plus:V2SF (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f")
+                                       (match_operand:V2SF 2 "gpc_reg_operand" "f"))
+                            (match_operand:V2SF 3 "gpc_reg_operand" "f"))))]
+  "TARGET_PAIRED_FLOAT && TARGET_FUSED_MADD
+   && HONOR_SIGNED_ZEROS (SFmode)"
+  "ps_nmadd %0,%1,%2,%3"
+  [(set_attr "type" "fp")])
+
+(define_insn "paired_nmsub"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (neg:V2SF (minus:V2SF (mult:V2SF (match_operand:V2SF 1 "gpc_reg_operand" "%f")
+                                        (match_operand:V2SF 2 "gpc_reg_operand" "f"))
+                             (match_operand:V2SF 3 "gpc_reg_operand" "f"))))]
+  "TARGET_PAIRED_FLOAT && TARGET_FUSED_MADD
+   && HONOR_SIGNED_ZEROS (DFmode)"
+  "ps_nmsub %0,%1,%2,%3"
+  [(set_attr "type" "dmul")])
+
+(define_insn "selv2sf4"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (vec_concat:V2SF
+        (if_then_else:SF (ge (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                                            (parallel [(const_int 0)]))
+                             (match_operand:SF 4 "zero_fp_constant" "F"))
+                         (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
+                                        (parallel [(const_int 0)]))
+                         (vec_select:SF (match_operand:V2SF 3 "gpc_reg_operand" "f")
+                                        (parallel [(const_int 0)])))
+        (if_then_else:SF (ge (vec_select:SF (match_dup 1)
+                                            (parallel [(const_int 1)]))
+                             (match_dup 4))
+                         (vec_select:SF (match_dup 2)
+                                        (parallel [(const_int 1)]))
+                         (vec_select:SF (match_dup 3)
+                                        (parallel [(const_int 1)])))))]
+
+  "TARGET_PAIRED_FLOAT"
+  "ps_sel %0,%1,%2,%3"
+  [(set_attr "type" "fp")])
+
+(define_insn "*movv2sf_paired"
+  [(set (match_operand:V2SF 0 "nonimmediate_operand" "=Z,f,f,o,r,r,v")
+                (match_operand:V2SF 1 "input_operand" "f,Z,f,r,o,r,W"))]
+  "TARGET_PAIRED_FLOAT
+   && (register_operand (operands[0], V2SFmode) 
+       || register_operand (operands[1], V2SFmode))"
+{
+  switch (which_alternative)
+    {
+    case 0: return "psq_stx %1,%y0,0,0";
+    case 1: return "psq_lx %0,%y1,0,0";
+    case 2: return "ps_mr %0,%1";
+    case 3: return "#";
+    case 4: return "#";
+    case 5: return "#";
+    case 6: return output_vec_const_move (operands);
+    default: gcc_unreachable ();
+    }
+}
+  [(set_attr "type" "fpstore,fpload,fp,*,*,*,*")])
+
+(define_insn "paired_stx"
+  [(set (match_operand:V2SF 0 "memory_operand" "=Z")
+        (match_operand:V2SF 1 "gpc_reg_operand" "f"))]
+  "TARGET_PAIRED_FLOAT"
+  "psq_stx %1,%y0,0,0"
+  [(set_attr "type" "fpstore")])
+
+(define_insn "paired_lx"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+        (match_operand:V2SF 1 "memory_operand" "Z"))]
+  "TARGET_PAIRED_FLOAT"
+  "psq_lx %0,%y1,0,0"
+  [(set_attr "type" "fpload")])
+
+
+(define_split
+  [(set (match_operand:V2SF 0 "nonimmediate_operand" "")
+        (match_operand:V2SF 1 "input_operand" ""))]
+  "TARGET_PAIRED_FLOAT && reload_completed
+   && gpr_or_gpr_p (operands[0], operands[1])"
+  [(pc)]
+  {
+  rs6000_split_multireg_move (operands[0], operands[1]); DONE;
+  })
+
+(define_insn "paired_cmpu0"
+  [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+       (compare:CCFP (vec_select:SF
+                      (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                      (parallel [(const_int 0)]))
+                     (vec_select:SF
+                      (match_operand:V2SF 2 "gpc_reg_operand" "f")
+                      (parallel [(const_int 0)]))))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_cmpu0 %0,%1,%2"
+  [(set_attr "type" "fpcompare")])
+
+(define_insn "paired_cmpu1"
+  [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+       (compare:CCFP (vec_select:SF
+                      (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                      (parallel [(const_int 1)]))
+                     (vec_select:SF
+                      (match_operand:V2SF 2 "gpc_reg_operand" "f")
+                      (parallel [(const_int 1)]))))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_cmpu1 %0,%1,%2"
+  [(set_attr "type" "fpcompare")])
+
+(define_insn "paired_merge00"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (vec_concat:V2SF
+        (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                       (parallel [(const_int 0)]))
+        (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
+                       (parallel [(const_int 0)]))))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_merge00 %0, %1, %2"
+  [(set_attr "type" "fp")])
+
+(define_insn "paired_merge01"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (vec_concat:V2SF
+        (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                       (parallel [(const_int 0)]))
+        (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
+                       (parallel [(const_int 1)]))))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_merge01 %0, %1, %2"
+  [(set_attr "type" "fp")])
+
+(define_insn "paired_merge10"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (vec_concat:V2SF
+        (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                       (parallel [(const_int 1)]))
+        (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
+                       (parallel [(const_int 0)]))))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_merge10 %0, %1, %2"
+  [(set_attr "type" "fp")])
+
+(define_insn "paired_merge11"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (vec_concat:V2SF
+        (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                       (parallel [(const_int 1)]))
+        (vec_select:SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
+                       (parallel [(const_int 1)]))))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_merge11 %0, %1, %2"
+  [(set_attr "type" "fp")])
+
+(define_insn "paired_sum0"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (vec_concat:V2SF (plus:SF (vec_select:SF
+                                  (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                                  (parallel [(const_int 0)]))
+                                 (vec_select:SF
+                                  (match_operand:V2SF 2 "gpc_reg_operand" "f")
+                                  (parallel [(const_int 1)])))
+                        (vec_select:SF
+                         (match_operand:V2SF 3 "gpc_reg_operand" "f")
+                         (parallel [(const_int 1)]))))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_sum0 %0,%1,%2,%3"
+  [(set_attr "type" "fp")])
+
+(define_insn "paired_sum1"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (vec_concat:V2SF (vec_select:SF
+                         (match_operand:V2SF 2 "gpc_reg_operand" "f")
+                         (parallel [(const_int 1)]))
+                        (plus:SF (vec_select:SF
+                                  (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                                  (parallel [(const_int 0)]))
+                                 (vec_select:SF
+                                  (match_operand:V2SF 3 "gpc_reg_operand" "f")
+                                  (parallel [(const_int 1)])))))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_sum1 %0,%1,%2,%3"
+  [(set_attr "type" "fp")])
+
+(define_insn "paired_muls0"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (mult:V2SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
+                  (vec_duplicate:V2SF
+                   (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                                  (parallel [(const_int 0)])))))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_muls0 %0, %1, %2"
+  [(set_attr "type" "fp")])
+
+
+(define_insn "paired_muls1"
+  [(set (match_operand:V2SF 0 "gpc_reg_operand" "=f")
+       (mult:V2SF (match_operand:V2SF 2 "gpc_reg_operand" "f")
+                  (vec_duplicate:V2SF
+                   (vec_select:SF (match_operand:V2SF 1 "gpc_reg_operand" "f")
+                                  (parallel [(const_int 1)])))))]
+  "TARGET_PAIRED_FLOAT"
+  "ps_muls1 %0, %1, %2"
+  [(set_attr "type" "fp")])
+
+
index 010b532993e783e43c8f5428359b1b999ccabb9d..03660b7ff07a5169868013aa1c8659966073ba42 100644 (file)
@@ -815,6 +815,12 @@ static void altivec_init_builtins (void);
 static void rs6000_common_init_builtins (void);
 static void rs6000_init_libfuncs (void);
 
+static void paired_init_builtins (void);
+static rtx paired_expand_builtin (tree, rtx, bool *);
+static rtx paired_expand_lv_builtin (enum insn_code, tree, rtx);
+static rtx paired_expand_stv_builtin (enum insn_code, tree);
+static rtx paired_expand_predicate_builtin (enum insn_code, tree, rtx);
+
 static void enable_mask_for_builtins (struct builtin_description *, int,
                                      enum rs6000_builtins,
                                      enum rs6000_builtins);
@@ -1224,12 +1230,14 @@ rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
      This excludes the 32-bit decimal float mode for now.  */
   if (FP_REGNO_P (regno))
     return
-      (SCALAR_FLOAT_MODE_P (mode)
+      ((SCALAR_FLOAT_MODE_P (mode)
        && (mode != TDmode || (regno % 2) == 0)
        && mode != SDmode
        && FP_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1))
       || (GET_MODE_CLASS (mode) == MODE_INT
-         && GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD);
+         && GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD)
+      || (PAIRED_SIMD_REGNO_P (regno) && TARGET_PAIRED_FLOAT
+           && PAIRED_VECTOR_MODE (mode)));
 
   /* The CR register can only hold CC modes.  */
   if (CR_REGNO_P (regno))
@@ -6594,7 +6602,7 @@ rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
 static void
 def_builtin (int mask, const char *name, tree type, int code)
 {
-  if (mask & target_flags)
+  if ((mask & target_flags) || TARGET_PAIRED_FLOAT)
     {
       if (rs6000_builtin_decls[code])
        abort ();
@@ -6648,6 +6656,15 @@ static const struct builtin_description bdesc_3arg[] =
   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_nmsub", ALTIVEC_BUILTIN_VEC_NMSUB },
   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_perm", ALTIVEC_BUILTIN_VEC_PERM },
   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sel", ALTIVEC_BUILTIN_VEC_SEL },
+
+  { 0, CODE_FOR_paired_msub, "__builtin_paired_msub", PAIRED_BUILTIN_MSUB },
+  { 0, CODE_FOR_paired_madd, "__builtin_paired_madd", PAIRED_BUILTIN_MADD },
+  { 0, CODE_FOR_paired_madds0, "__builtin_paired_madds0", PAIRED_BUILTIN_MADDS0 },
+  { 0, CODE_FOR_paired_madds1, "__builtin_paired_madds1", PAIRED_BUILTIN_MADDS1 },
+  { 0, CODE_FOR_paired_nmsub, "__builtin_paired_nmsub", PAIRED_BUILTIN_NMSUB },
+  { 0, CODE_FOR_paired_nmadd, "__builtin_paired_nmadd", PAIRED_BUILTIN_NMADD },
+  { 0, CODE_FOR_paired_sum0, "__builtin_paired_sum0", PAIRED_BUILTIN_SUM0 },
+  { 0, CODE_FOR_paired_sum1, "__builtin_paired_sum1", PAIRED_BUILTIN_SUM1 },
 };
 
 /* DST operations: void foo (void *, const int, const char).  */
@@ -6909,6 +6926,17 @@ static struct builtin_description bdesc_2arg[] =
   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sums", ALTIVEC_BUILTIN_VEC_SUMS },
   { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR },
 
+  { 0, CODE_FOR_divv2sf3, "__builtin_paired_divv2sf3", PAIRED_BUILTIN_DIVV2SF3 },
+  { 0, CODE_FOR_addv2sf3, "__builtin_paired_addv2sf3", PAIRED_BUILTIN_ADDV2SF3 },
+  { 0, CODE_FOR_subv2sf3, "__builtin_paired_subv2sf3", PAIRED_BUILTIN_SUBV2SF3 },
+  { 0, CODE_FOR_mulv2sf3, "__builtin_paired_mulv2sf3", PAIRED_BUILTIN_MULV2SF3 },
+  { 0, CODE_FOR_paired_muls0, "__builtin_paired_muls0", PAIRED_BUILTIN_MULS0 },
+  { 0, CODE_FOR_paired_muls1, "__builtin_paired_muls1", PAIRED_BUILTIN_MULS1 },
+  { 0, CODE_FOR_paired_merge00, "__builtin_paired_merge00", PAIRED_BUILTIN_MERGE00 },
+  { 0, CODE_FOR_paired_merge01, "__builtin_paired_merge01", PAIRED_BUILTIN_MERGE01 },
+  { 0, CODE_FOR_paired_merge10, "__builtin_paired_merge10", PAIRED_BUILTIN_MERGE10 },
+  { 0, CODE_FOR_paired_merge11, "__builtin_paired_merge11", PAIRED_BUILTIN_MERGE11 },
+
   /* Place holder, leave as first spe builtin.  */
   { 0, CODE_FOR_spe_evaddw, "__builtin_spe_evaddw", SPE_BUILTIN_EVADDW },
   { 0, CODE_FOR_spe_evand, "__builtin_spe_evand", SPE_BUILTIN_EVAND },
@@ -7122,6 +7150,15 @@ static struct builtin_description bdesc_spe_evsel[] =
   { 0, CODE_FOR_spe_evfststeq, "__builtin_spe_evsel_fststeq", SPE_BUILTIN_EVSEL_FSTSTEQ },
 };
 
+/* PAIRED predicates.  */
+static const struct builtin_description bdesc_paired_preds[] =
+{
+  /* Place-holder.  Leave as first.  */
+  { 0, CODE_FOR_paired_cmpu0, "__builtin_paired_cmpu0", PAIRED_BUILTIN_CMPU0 },
+  /* Place-holder.  Leave as last.  */
+  { 0, CODE_FOR_paired_cmpu1, "__builtin_paired_cmpu1", PAIRED_BUILTIN_CMPU1 },
+};
+
 /* ABS* operations.  */
 
 static const struct builtin_description bdesc_abs[] =
@@ -7210,7 +7247,13 @@ static struct builtin_description bdesc_1arg[] =
   { 0, CODE_FOR_spe_evsubfumiaaw, "__builtin_spe_evsubfumiaaw", SPE_BUILTIN_EVSUBFUMIAAW },
 
   /* Place-holder.  Leave as last unary SPE builtin.  */
-  { 0, CODE_FOR_spe_evsubfusiaaw, "__builtin_spe_evsubfusiaaw", SPE_BUILTIN_EVSUBFUSIAAW }
+  { 0, CODE_FOR_spe_evsubfusiaaw, "__builtin_spe_evsubfusiaaw", SPE_BUILTIN_EVSUBFUSIAAW },
+
+  { 0, CODE_FOR_absv2sf2, "__builtin_paired_absv2sf2", PAIRED_BUILTIN_ABSV2SF2 },
+  { 0, CODE_FOR_nabsv2sf2, "__builtin_paired_nabsv2sf2", PAIRED_BUILTIN_NABSV2SF2 },
+  { 0, CODE_FOR_negv2sf2, "__builtin_paired_negv2sf2", PAIRED_BUILTIN_NEGV2SF2 },
+  { 0, CODE_FOR_sqrtv2sf2, "__builtin_paired_sqrtv2sf2", PAIRED_BUILTIN_SQRTV2SF2 },
+  { 0, CODE_FOR_resv2sf2, "__builtin_paired_resv2sf2", PAIRED_BUILTIN_RESV2SF2 }
 };
 
 static rtx
@@ -7444,6 +7487,52 @@ altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode,
   return target;
 }
 
+static rtx
+paired_expand_lv_builtin (enum insn_code icode, tree exp, rtx target)
+{
+  rtx pat, addr;
+  tree arg0 = CALL_EXPR_ARG (exp, 0);
+  tree arg1 = CALL_EXPR_ARG (exp, 1);
+  enum machine_mode tmode = insn_data[icode].operand[0].mode;
+  enum machine_mode mode0 = Pmode;
+  enum machine_mode mode1 = Pmode;
+  rtx op0 = expand_normal (arg0);
+  rtx op1 = expand_normal (arg1);
+
+  if (icode == CODE_FOR_nothing)
+    /* Builtin not supported on this processor.  */
+    return 0;
+
+  /* If we got invalid arguments bail out before generating bad rtl.  */
+  if (arg0 == error_mark_node || arg1 == error_mark_node)
+    return const0_rtx;
+
+  if (target == 0
+      || GET_MODE (target) != tmode
+      || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+    target = gen_reg_rtx (tmode);
+
+  op1 = copy_to_mode_reg (mode1, op1);
+
+  if (op0 == const0_rtx)
+    {
+      addr = gen_rtx_MEM (tmode, op1);
+    }
+  else
+    {
+      op0 = copy_to_mode_reg (mode0, op0);
+      addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op0, op1));
+    }
+
+  pat = GEN_FCN (icode) (target, addr);
+
+  if (! pat)
+    return 0;
+  emit_insn (pat);
+
+  return target;
+}
+
 static rtx
 altivec_expand_lv_builtin (enum insn_code icode, tree exp, rtx target)
 {
@@ -7523,6 +7612,47 @@ spe_expand_stv_builtin (enum insn_code icode, tree exp)
   return NULL_RTX;
 }
 
+static rtx
+paired_expand_stv_builtin (enum insn_code icode, tree exp)
+{
+  tree arg0 = CALL_EXPR_ARG (exp, 0);
+  tree arg1 = CALL_EXPR_ARG (exp, 1);
+  tree arg2 = CALL_EXPR_ARG (exp, 2);
+  rtx op0 = expand_normal (arg0);
+  rtx op1 = expand_normal (arg1);
+  rtx op2 = expand_normal (arg2);
+  rtx pat, addr;
+  enum machine_mode tmode = insn_data[icode].operand[0].mode;
+  enum machine_mode mode1 = Pmode;
+  enum machine_mode mode2 = Pmode;
+
+  /* Invalid arguments.  Bail before doing anything stoopid!  */
+  if (arg0 == error_mark_node
+      || arg1 == error_mark_node
+      || arg2 == error_mark_node)
+    return const0_rtx;
+
+  if (! (*insn_data[icode].operand[1].predicate) (op0, tmode))
+    op0 = copy_to_mode_reg (tmode, op0);
+
+  op2 = copy_to_mode_reg (mode2, op2);
+
+  if (op1 == const0_rtx)
+    {
+      addr = gen_rtx_MEM (tmode, op2);
+    }
+  else
+    {
+      op1 = copy_to_mode_reg (mode1, op1);
+      addr = gen_rtx_MEM (tmode, gen_rtx_PLUS (Pmode, op1, op2));
+    }
+
+  pat = GEN_FCN (icode) (addr, op0);
+  if (pat)
+    emit_insn (pat);
+  return NULL_RTX;
+}
+
 static rtx
 altivec_expand_stv_builtin (enum insn_code icode, tree exp)
 {
@@ -8071,6 +8201,39 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
   return NULL_RTX;
 }
 
+/* Expand the builtin in EXP and store the result in TARGET.  Store
+   true in *EXPANDEDP if we found a builtin to expand.  */
+static rtx
+paired_expand_builtin (tree exp, rtx target, bool * expandedp)
+{
+  tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
+  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+  struct builtin_description *d;
+  size_t i;
+
+  *expandedp = true;
+
+  switch (fcode)
+    {
+    case PAIRED_BUILTIN_STX:
+      return paired_expand_stv_builtin (CODE_FOR_paired_stx, exp);
+    case PAIRED_BUILTIN_LX:
+      return paired_expand_lv_builtin (CODE_FOR_paired_lx, exp, target);
+    default:
+      break;
+      /* Fall through.  */
+    }
+
+  /* Expand the paired predicates.  */
+  d = (struct builtin_description *) bdesc_paired_preds;
+  for (i = 0; i < ARRAY_SIZE (bdesc_paired_preds); i++, d++)
+    if (d->code == fcode)
+      return paired_expand_predicate_builtin (d->icode, exp, target);
+
+  *expandedp = false;
+  return NULL_RTX;
+}
+
 /* Binops that need to be initialized manually, but can be expanded
    automagically by rs6000_expand_binop_builtin.  */
 static struct builtin_description bdesc_2arg_spe[] =
@@ -8236,6 +8399,78 @@ spe_expand_builtin (tree exp, rtx target, bool *expandedp)
   return NULL_RTX;
 }
 
+static rtx
+paired_expand_predicate_builtin (enum insn_code icode, tree exp, rtx target)
+{
+  rtx pat, scratch, tmp;
+  tree form = CALL_EXPR_ARG (exp, 0);
+  tree arg0 = CALL_EXPR_ARG (exp, 1);
+  tree arg1 = CALL_EXPR_ARG (exp, 2);
+  rtx op0 = expand_normal (arg0);
+  rtx op1 = expand_normal (arg1);
+  enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+  enum machine_mode mode1 = insn_data[icode].operand[2].mode;
+  int form_int;
+  enum rtx_code code;
+
+  if (TREE_CODE (form) != INTEGER_CST)
+    {
+      error ("argument 1 of __builtin_paired_predicate must be a constant");
+      return const0_rtx;
+    }
+  else
+    form_int = TREE_INT_CST_LOW (form);
+
+  gcc_assert (mode0 == mode1);
+
+  if (arg0 == error_mark_node || arg1 == error_mark_node)
+    return const0_rtx;
+
+  if (target == 0
+      || GET_MODE (target) != SImode
+      || !(*insn_data[icode].operand[0].predicate) (target, SImode))
+    target = gen_reg_rtx (SImode);
+  if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
+    op0 = copy_to_mode_reg (mode0, op0);
+  if (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
+    op1 = copy_to_mode_reg (mode1, op1);
+
+  scratch = gen_reg_rtx (CCFPmode);
+
+  pat = GEN_FCN (icode) (scratch, op0, op1);
+  if (!pat)
+    return const0_rtx;
+
+  emit_insn (pat);
+
+  switch (form_int)
+    {
+      /* LT bit.  */
+    case 0:
+      code = LT;
+      break;
+      /* GT bit.  */
+    case 1:
+      code = GT;
+      break;
+      /* EQ bit.  */
+    case 2:
+      code = EQ;
+      break;
+      /* UN bit.  */
+    case 3:
+      emit_insn (gen_move_from_CR_ov_bit (target, scratch));
+      return target;
+    default:
+      error ("argument 1 of __builtin_paired_predicate is out of range");
+      return const0_rtx;
+    }
+
+  tmp = gen_rtx_fmt_ee (code, SImode, scratch, const0_rtx);
+  emit_move_insn (target, tmp);
+  return target;
+}
+
 static rtx
 spe_expand_predicate_builtin (enum insn_code icode, tree exp, rtx target)
 {
@@ -8476,8 +8711,15 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
       if (success)
        return ret;
     }
+  if (TARGET_PAIRED_FLOAT)
+    {
+      ret = paired_expand_builtin (exp, target, &success);
+
+      if (success)
+       return ret;
+    }  
 
-  gcc_assert (TARGET_ALTIVEC || TARGET_SPE);
+  gcc_assert (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT);
 
   /* Handle simple unary operations.  */
   d = (struct builtin_description *) bdesc_1arg;
@@ -8603,11 +8845,13 @@ rs6000_init_builtins (void)
                                            get_identifier ("__vector __pixel"),
                                            pixel_V8HI_type_node));
 
+  if (TARGET_PAIRED_FLOAT)
+    paired_init_builtins ();
   if (TARGET_SPE)
     spe_init_builtins ();
   if (TARGET_ALTIVEC)
     altivec_init_builtins ();
-  if (TARGET_ALTIVEC || TARGET_SPE)
+  if (TARGET_ALTIVEC || TARGET_SPE || TARGET_PAIRED_FLOAT)
     rs6000_common_init_builtins ();
 
 #if TARGET_XCOFF
@@ -8864,6 +9108,62 @@ spe_init_builtins (void)
     }
 }
 
+static void
+paired_init_builtins (void)
+{
+  struct builtin_description *d;
+  size_t i;
+  tree endlink = void_list_node;
+
+   tree int_ftype_int_v2sf_v2sf
+    = build_function_type
+    (integer_type_node,
+     tree_cons (NULL_TREE, integer_type_node,
+                tree_cons (NULL_TREE, V2SF_type_node,
+                           tree_cons (NULL_TREE, V2SF_type_node,
+                                      endlink))));
+  tree pcfloat_type_node =
+    build_pointer_type (build_qualified_type
+                       (float_type_node, TYPE_QUAL_CONST));
+
+  tree v2sf_ftype_long_pcfloat = build_function_type_list (V2SF_type_node,
+                                                          long_integer_type_node,
+                                                          pcfloat_type_node,
+                                                          NULL_TREE);
+  tree void_ftype_v2sf_long_pcfloat =
+    build_function_type_list (void_type_node,
+                             V2SF_type_node,
+                             long_integer_type_node,
+                             pcfloat_type_node,
+                             NULL_TREE);
+
+
+  def_builtin (0, "__builtin_paired_lx", v2sf_ftype_long_pcfloat,
+              PAIRED_BUILTIN_LX);
+
+
+  def_builtin (0, "__builtin_paired_stx", void_ftype_v2sf_long_pcfloat,
+              PAIRED_BUILTIN_STX);
+
+  /* Predicates.  */
+  d = (struct builtin_description *) bdesc_paired_preds;
+  for (i = 0; i < ARRAY_SIZE (bdesc_paired_preds); ++i, d++)
+    {
+      tree type;
+
+      switch (insn_data[d->icode].operand[1].mode)
+       {
+       case V2SFmode:
+         type = int_ftype_int_v2sf_v2sf;
+         break;
+       default:
+         gcc_unreachable ();
+       }
+
+      def_builtin (d->mask, d->name, type, d->code);
+    }
+}
+
 static void
 altivec_init_builtins (void)
 {
@@ -9226,6 +9526,11 @@ rs6000_common_init_builtins (void)
   const struct builtin_description *d;
   size_t i;
 
+  tree v2sf_ftype_v2sf_v2sf_v2sf
+    = build_function_type_list (V2SF_type_node,
+                                V2SF_type_node, V2SF_type_node,
+                                V2SF_type_node, NULL_TREE);
+
   tree v4sf_ftype_v4sf_v4sf_v16qi
     = build_function_type_list (V4SF_type_node,
                                V4SF_type_node, V4SF_type_node,
@@ -9258,11 +9563,17 @@ rs6000_common_init_builtins (void)
                                opaque_V2SI_type_node,
                                opaque_V2SI_type_node, NULL_TREE);
 
-  tree v2sf_ftype_v2sf_v2sf
+  tree v2sf_ftype_v2sf_v2sf_spe
     = build_function_type_list (opaque_V2SF_type_node,
                                opaque_V2SF_type_node,
                                opaque_V2SF_type_node, NULL_TREE);
 
+  tree v2sf_ftype_v2sf_v2sf
+    = build_function_type_list (V2SF_type_node,
+                                V2SF_type_node,
+                                V2SF_type_node, NULL_TREE);
+
+
   tree v2si_ftype_int_int
     = build_function_type_list (opaque_V2SI_type_node,
                                integer_type_node, integer_type_node,
@@ -9276,10 +9587,14 @@ rs6000_common_init_builtins (void)
     = build_function_type_list (opaque_V2SI_type_node,
                                opaque_V2SI_type_node, NULL_TREE);
 
-  tree v2sf_ftype_v2sf
+  tree v2sf_ftype_v2sf_spe
     = build_function_type_list (opaque_V2SF_type_node,
                                opaque_V2SF_type_node, NULL_TREE);
 
+  tree v2sf_ftype_v2sf
+    = build_function_type_list (V2SF_type_node,
+                                V2SF_type_node, NULL_TREE);
+
   tree v2sf_ftype_v2si
     = build_function_type_list (opaque_V2SF_type_node,
                                opaque_V2SI_type_node, NULL_TREE);
@@ -9466,6 +9781,9 @@ rs6000_common_init_builtins (void)
            case V16QImode:
              type = v16qi_ftype_v16qi_v16qi_v16qi;
              break;
+            case V2SFmode:
+                type = v2sf_ftype_v2sf_v2sf_v2sf;
+              break;
            default:
              gcc_unreachable ();
            }
@@ -9574,8 +9892,11 @@ rs6000_common_init_builtins (void)
            case V2SImode:
              type = v2si_ftype_v2si_v2si;
              break;
-           case V2SFmode:
-             type = v2sf_ftype_v2sf_v2sf;
+            case V2SFmode:
+              if (TARGET_PAIRED_FLOAT)
+                type = v2sf_ftype_v2sf_v2sf;
+              else
+                type = v2sf_ftype_v2sf_v2sf_spe;
              break;
            case SImode:
              type = int_ftype_int_int;
@@ -9714,7 +10035,12 @@ rs6000_common_init_builtins (void)
       else if (mode0 == V2SImode && mode1 == V2SImode)
        type = v2si_ftype_v2si;
       else if (mode0 == V2SFmode && mode1 == V2SFmode)
-       type = v2sf_ftype_v2sf;
+        {
+          if (TARGET_PAIRED_FLOAT)
+            type = v2sf_ftype_v2sf;
+          else
+            type = v2sf_ftype_v2sf_spe;
+        }
       else if (mode0 == V2SFmode && mode1 == V2SImode)
        type = v2sf_ftype_v2si;
       else if (mode0 == V2SImode && mode1 == V2SFmode)
@@ -21094,6 +21420,9 @@ static bool
 rs6000_vector_mode_supported_p (enum machine_mode mode)
 {
 
+  if (TARGET_PAIRED_FLOAT && PAIRED_VECTOR_MODE (mode))
+    return true;
+
   if (TARGET_SPE && SPE_VECTOR_MODE (mode))
     return true;
 
index 4ba955f4c82a9d37286a20ca687275d392a753b5..b7dced33aad1bc2db6fd2e9cf8b1e8a2d1d64315 100644 (file)
 #define PPC405_ERRATUM77 0
 #endif
 
+#ifndef TARGET_PAIRED_FLOAT
+#define TARGET_PAIRED_FLOAT 0
+#endif
+
 /* Common ASM definitions used by ASM_SPEC among the various targets
    for handling -mcpu=xxx switches.  */
 #define ASM_CPU_SPEC \
@@ -472,6 +476,7 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
 #define UNITS_PER_FP_WORD 8
 #define UNITS_PER_ALTIVEC_WORD 16
 #define UNITS_PER_SPE_WORD 8
+#define UNITS_PER_PAIRED_WORD 8
 
 /* Type used for ptrdiff_t, as a string used in a declaration.  */
 #define PTRDIFF_TYPE "int"
@@ -555,8 +560,10 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
 #define LOCAL_ALIGNMENT(TYPE, ALIGN)                           \
   ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
     (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 : \
-    (TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \
-     && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) ? 64 : ALIGN)
+    ((TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \
+     && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) || (TARGET_PAIRED_FLOAT \
+        && TREE_CODE (TYPE) == VECTOR_TYPE \
+        && PAIRED_VECTOR_MODE (TYPE_MODE (TYPE)))) ? 64 : ALIGN)
 
 /* Alignment of field after `int : 0' in a structure.  */
 #define EMPTY_FIELD_BOUNDARY 32
@@ -595,7 +602,8 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
    Align vectors to 128 bits.  Align SPE vectors and E500 v2 doubles to
    64 bits.  */
 #define DATA_ALIGNMENT(TYPE, ALIGN)            \
-  (TREE_CODE (TYPE) == VECTOR_TYPE ? (TARGET_SPE_ABI ? 64 : 128)       \
+  (TREE_CODE (TYPE) == VECTOR_TYPE ? ((TARGET_SPE_ABI \
+   || TARGET_PAIRED_FLOAT) ? 64 : 128) \
    : (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 \
    : TREE_CODE (TYPE) == ARRAY_TYPE            \
    && TYPE_MODE (TREE_TYPE (TYPE)) == QImode   \
@@ -831,6 +839,9 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
 /* SPE SIMD registers are just the GPRs.  */
 #define SPE_SIMD_REGNO_P(N) ((N) <= 31)
 
+/* PAIRED SIMD registers are just the FPRs.  */
+#define PAIRED_SIMD_REGNO_P(N) ((N) >= 32 && (N) <= 63)
+
 /* True if register is the XER register.  */
 #define XER_REGNO_P(N) ((N) == XER_REGNO)
 
@@ -859,9 +870,13 @@ extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
          || (MODE) == V1DImode          \
          || (MODE) == V2SImode)
 
-#define UNITS_PER_SIMD_WORD                                    \
-        (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD               \
-        : (TARGET_SPE ? UNITS_PER_SPE_WORD : UNITS_PER_WORD))
+#define PAIRED_VECTOR_MODE(MODE)        \
+         ((MODE) == V2SFmode)            
+
+#define UNITS_PER_SIMD_WORD                                         \
+       (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD                     \
+        : (TARGET_SPE ? UNITS_PER_SPE_WORD : (TARGET_PAIRED_FLOAT ? \
+        UNITS_PER_PAIRED_WORD : UNITS_PER_WORD)))
 
 /* Value is TRUE if hard register REGNO can hold a value of
    machine-mode MODE.  */
@@ -2949,6 +2964,35 @@ enum rs6000_builtins
   SPE_BUILTIN_MFSPEFSCR,
   SPE_BUILTIN_BRINC,
 
+  /* PAIRED builtins.  */
+  PAIRED_BUILTIN_DIVV2SF3,
+  PAIRED_BUILTIN_ABSV2SF2,
+  PAIRED_BUILTIN_NEGV2SF2,
+  PAIRED_BUILTIN_SQRTV2SF2,
+  PAIRED_BUILTIN_ADDV2SF3,
+  PAIRED_BUILTIN_SUBV2SF3,
+  PAIRED_BUILTIN_RESV2SF2,
+  PAIRED_BUILTIN_MULV2SF3,
+  PAIRED_BUILTIN_MSUB,
+  PAIRED_BUILTIN_MADD,
+  PAIRED_BUILTIN_NMSUB,
+  PAIRED_BUILTIN_NMADD,
+  PAIRED_BUILTIN_NABSV2SF2,
+  PAIRED_BUILTIN_SUM0,
+  PAIRED_BUILTIN_SUM1,
+  PAIRED_BUILTIN_MULS0,
+  PAIRED_BUILTIN_MULS1,
+  PAIRED_BUILTIN_MERGE00,
+  PAIRED_BUILTIN_MERGE01,
+  PAIRED_BUILTIN_MERGE10,
+  PAIRED_BUILTIN_MERGE11,
+  PAIRED_BUILTIN_MADDS0,
+  PAIRED_BUILTIN_MADDS1,
+  PAIRED_BUILTIN_STX,
+  PAIRED_BUILTIN_LX,
+  PAIRED_BUILTIN_CMPU0,
+  PAIRED_BUILTIN_CMPU1,
+
   RS6000_BUILTIN_COUNT
 };
 
index 4bc711282785d58e3ff2f7ac6855ff6c91370a47..e3505d1e5ae83c497ba7adb3dd09bddd98830ad1 100644 (file)
 (include "altivec.md")
 (include "spe.md")
 (include "dfp.md")
+(include "paired.md")
index cfa123ab4b0dadf9b613646913ee444eac2e9002..49800633935b8f94111feb1920fa6eb256adaa79 100644 (file)
@@ -201,6 +201,10 @@ mspe
 Target Var(rs6000_spe)
 Generate SPE SIMD instructions on E500
 
+mpaired
+Target Var(rs6000_paired_float)
+Generate PPC750CL paired-single instructions
+
 mspe=
 Target RejectNegative Joined
 -mspe=yes/no   Deprecated option.  Use -mspe/-mno-spe instead
index b7b2fef8eab8b1e5ce4405b89cd0be6822cf313d..1b66343bab2cf1edaa266e9064846b87a451a18d 100644 (file)
 (define_expand "movv2sf"
   [(set (match_operand:V2SF 0 "nonimmediate_operand" "")
        (match_operand:V2SF 1 "any_operand" ""))]
-  "TARGET_SPE"
+  "TARGET_SPE || TARGET_PAIRED_FLOAT"
   "{ rs6000_emit_move (operands[0], operands[1], V2SFmode); DONE; }")
 
 (define_insn "*movv2sf_internal"
index 1646df305cb4f154ea3cf16b2728aeb59d614835..61b7f72493d279c648fbf588032fc219d0401598 100644 (file)
@@ -704,6 +704,7 @@ See RS/6000 and PowerPC Options.
 -misel=yes  -misel=no @gol
 -mspe -mno-spe @gol
 -mspe=yes  -mspe=no @gol
+-mpaired @gol
 -mvrsave -mno-vrsave @gol
 -mmulhw -mno-mulhw @gol
 -mdlmzb -mno-dlmzb @gol
@@ -12582,6 +12583,13 @@ This switch has been deprecated.  Use @option{-misel} and
 This switch enables or disables the generation of SPE simd
 instructions.
 
+@item -mpaired
+@itemx -mno-paired
+@opindex mpaired
+@opindex mno-paired
+This switch enables or disables the generation of PAIRED simd
+instructions.
+
 @item -mspe=@var{yes/no}
 This option has been deprecated.  Use @option{-mspe} and
 @option{-mno-spe} instead.
index 80f20333b7007c03325a432da608f5d56e599925..f3d9fd7a417051ca03d02c2aad15758b17f7c7b9 100644 (file)
@@ -1,3 +1,15 @@
+2007-08-31  David Edelsohn  <edelsohn@gnu.org>
+            Revital Eres  <eres@il.ibm.com>
+
+        * gcc.target/powerpc/paired-1.c: New test.
+        * gcc.target/powerpc/paired-2.c: New test.
+        * gcc.target/powerpc/paired-3.c: New test.
+        * gcc.target/powerpc/paired-4.c: New test.
+        * gcc.target/powerpc/paired-5.c: New test.
+        * gcc.target/powerpc/paired-6.c: New test.
+        * gcc.target/powerpc/paired-7.c: New test.
+        * gcc.target/powerpc/ppc-paired.c: New test.
+
 2007-08-30  Ollie Wild  <aaw@google.com>
 
        g++.dg/conversion/ptrmem2.C: New test.
diff --git a/gcc/testsuite/gcc.target/powerpc/paired-1.c b/gcc/testsuite/gcc.target/powerpc/paired-1.c
new file mode 100644 (file)
index 0000000..641a8e0
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile { target powerpc-*-linux*paired* } } */
+/* { dg-options "-mpaired -m32 -ffinite-math-only " } */
+
+/* Test PowerPC PAIRED extensions.  */
+
+#include <paired.h>
+
+static float in1[2] __attribute__ ((aligned (8))) =
+{6.0, 7.0};
+static float in2[2] __attribute__ ((aligned (8))) =
+{4.0, 3.0};
+
+static float out[2] __attribute__ ((aligned (8)));
+
+vector float a, b, c, d;
+void
+test_api ()
+{
+  b = paired_lx (0, in1);
+  c = paired_lx (0, in2);
+
+  a = paired_sub (b, c);
+
+  paired_stx (a, 0, out);
+}
+
+int
+main ()
+{
+  test_api ();
+  return (0);
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/paired-2.c b/gcc/testsuite/gcc.target/powerpc/paired-2.c
new file mode 100644 (file)
index 0000000..ef40902
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile { target powerpc-*-linux*paired* } } */
+/* { dg-options "-mpaired -m32 -ffinite-math-only" } */
+
+/* Test PowerPC PAIRED extensions.  */
+
+#include <paired.h>
+#include <stdlib.h>
+
+static float out[2] __attribute__ ((aligned (8)));
+
+vector float b = { 3.0, 8.0 };
+vector float c = { 3.0, 5.0 };
+
+vector float a = { 0.0, 0.0 };
+void
+test_api ()
+{
+
+  if (paired_cmpu0_eq (b, c))
+    {
+      a = paired_sub (b, c);
+      paired_stx (a, 0, out);
+    }
+
+  if ((out[1]) != 3.0)
+    abort ();
+}
+
+int
+main ()
+{
+  test_api ();
+  return (0);
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/paired-3.c b/gcc/testsuite/gcc.target/powerpc/paired-3.c
new file mode 100644 (file)
index 0000000..756d6e1
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do compile { target powerpc-*-linux*paired* } } */
+/* { dg-options "-mpaired -m32 -ffinite-math-only" } */
+
+/* Test PowerPC PAIRED extensions.  */
+
+#include <paired.h>
+#include <stdlib.h>
+
+static float out[2] __attribute__ ((aligned (8)));
+
+vector float b = { 2.0, 8.0 };
+vector float c = { 3.0, 5.0 };
+
+vector float a = { 0.0, 0.0 };
+void
+test_api ()
+{
+
+  if (paired_cmpu0_lt (b, c))
+    {
+      a = paired_add (b, c);
+      paired_stx (a, 0, out);
+    }
+  if ((out[0] != 5.0) || (out[1] != 13.0))
+    abort ();
+}
+
+int
+main ()
+{
+  test_api ();
+  return (0);
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/paired-4.c b/gcc/testsuite/gcc.target/powerpc/paired-4.c
new file mode 100644 (file)
index 0000000..3d5c154
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do compile { target powerpc-*-linux*paired* } } */
+/* { dg-options "-mpaired -m32 -ffinite-math-only" } */
+
+/* Test PowerPC PAIRED extensions.  */
+
+#include <paired.h>
+#include <stdlib.h>
+
+static float out[2] __attribute__ ((aligned (8)));
+
+vector float b = { 3.0, 8.0 };
+vector float c = { 2.0, 5.0 };
+
+vector float a = { 0.0, 0.0 };
+void
+test_api ()
+{
+
+  if (paired_cmpu0_gt (b, c))
+    {
+      a = paired_add (b, c);
+      paired_stx (a, 0, out);
+    }
+  if ((out[0] != 5.0) || (out[1] != 13.0))
+    abort ();
+}
+
+int
+main ()
+{
+  test_api ();
+  return (0);
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/paired-5.c b/gcc/testsuite/gcc.target/powerpc/paired-5.c
new file mode 100644 (file)
index 0000000..df3bb44
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do compile { target powerpc-*-linux*paired* } } */
+/* { dg-options "-mpaired -m32 -ffinite-math-only" } */
+
+/* Test PowerPC PAIRED extensions.  */
+
+#include <paired.h>
+#include <stdlib.h>
+
+static float out[2] __attribute__ ((aligned (8)));
+
+vector float b = { 3.0, 5.0 };
+vector float c = { 2.0, 5.0 };
+
+vector float a = { 0.0, 0.0 };
+void
+test_api ()
+{
+
+  if (paired_cmpu1_eq (b, c))
+    {
+      a = paired_add (b, c);
+      paired_stx (a, 0, out);
+    }
+  if ((out[0] != 5.0) || (out[1] != 10.0))
+    abort ();
+}
+
+int
+main ()
+{
+  test_api ();
+  return (0);
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/paired-6.c b/gcc/testsuite/gcc.target/powerpc/paired-6.c
new file mode 100644 (file)
index 0000000..0d6ab52
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do compile { target powerpc-*-linux*paired* } } */
+/* { dg-options "-mpaired -m32 -ffinite-math-only" } */
+
+/* Test PowerPC PAIRED extensions.  */
+
+#include <paired.h>
+#include <stdlib.h>
+
+static float out[2] __attribute__ ((aligned (8)));
+
+vector float b = { 3.0, 5.0 };
+vector float c = { 2.0, 6.0 };
+
+vector float a = { 0.0, 0.0 };
+void
+test_api ()
+{
+
+  if (paired_cmpu1_lt (b, c))
+    {
+      a = paired_add (b, c);
+      paired_stx (a, 0, out);
+    }
+  if ((out[0] != 5.0) || (out[1] != 11.0))
+    abort ();
+}
+
+int
+main ()
+{
+  test_api ();
+  return (0);
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/paired-7.c b/gcc/testsuite/gcc.target/powerpc/paired-7.c
new file mode 100644 (file)
index 0000000..aa1edd0
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do compile { target powerpc-*-linux*paired* } } */
+/* { dg-options "-mpaired -m32 -ffinite-math-only" } */
+
+/* Test PowerPC PAIRED extensions.  */
+
+#include <paired.h>
+#include <stdlib.h>
+
+static float out[2] __attribute__ ((aligned (8)));
+
+vector float b = { 2.0, 8.0 };
+vector float c = { 3.0, 6.0 };
+
+vector float a = { 0.0, 0.0 };
+void
+test_api ()
+{
+
+  if (paired_cmpu1_gt (b, c))
+    {
+      a = paired_add (b, c);
+      paired_stx (a, 0, out);
+    }
+  if ((out[0] != 5.0) || (out[1] != 14.0))
+    abort ();
+}
+
+int
+main ()
+{
+  test_api ();
+  return (0);
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/ppc-paired.c b/gcc/testsuite/gcc.target/powerpc/ppc-paired.c
new file mode 100644 (file)
index 0000000..f6f3b6e
--- /dev/null
@@ -0,0 +1,44 @@
+/* { dg-do compile { target powerpc-*-linux*paired* } } */
+/* { dg-options "-mpaired -m32 -ffinite-math-only" } */
+
+/* Test PowerPC PAIRED extensions.  */
+
+#include <paired.h>
+
+vector float a, b, c, d;
+
+void
+test_api ()
+{
+  b = paired_msub (b, c, d);
+  b = paired_madd (b, c, d);
+  b = paired_nmadd (b, c, d);
+  b = paired_nmsub (b, c, d);
+  b = paired_sum0 (a, b, c);
+  b = paired_sum1 (a, b, c);
+  b = paired_div (b, c);
+  b = paired_add (a, c);
+  b = paired_sub (a, c);
+  b = paired_mul (a, c);
+  b = paired_neg (a);
+  b = paired_muls0 (a, c);
+  b = paired_muls1 (a, c);
+  b = paired_madds0 (a, c, d);
+  b = paired_madds1 (a, c, d);
+  b = paired_merge00 (a, c);
+  b = paired_merge01 (a, c);
+  b = paired_merge10 (a, c);
+  b = paired_merge11 (a, c);
+  b = paired_abs (a);
+  b = paired_nabs (a);
+  b = paired_sqrt (a);
+  b = paired_res (a);
+}
+
+int
+main (void)
+{
+  test_api ();
+  return 0;
+}
+