summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrevitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4>2007-08-31 05:26:38 +0000
committerrevitale <revitale@138bc75d-0d04-0410-961f-82ee72b054a4>2007-08-31 05:26:38 +0000
commita9de045e3994baa4e0ccb0bc3055e7ef3e697cd7 (patch)
treef6b30b9a0ef62545c6daf229e0c8c8eff0aa2a72
parente5ead12a0cb23e024117b90a912c24efd36f995a (diff)
downloadgcc-a9de045e3994baa4e0ccb0bc3055e7ef3e697cd7.tar.gz
Support for PowerPC 750CL paired-single instructions
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@127954 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog36
-rw-r--r--gcc/config.gcc7
-rw-r--r--gcc/config/rs6000/750cl.h23
-rw-r--r--gcc/config/rs6000/paired.h77
-rw-r--r--gcc/config/rs6000/paired.md355
-rw-r--r--gcc/config/rs6000/rs6000.c351
-rw-r--r--gcc/config/rs6000/rs6000.h56
-rw-r--r--gcc/config/rs6000/rs6000.md1
-rw-r--r--gcc/config/rs6000/rs6000.opt4
-rw-r--r--gcc/config/rs6000/spe.md2
-rw-r--r--gcc/doc/invoke.texi8
-rw-r--r--gcc/testsuite/ChangeLog12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/paired-1.c33
-rw-r--r--gcc/testsuite/gcc.target/powerpc/paired-2.c35
-rw-r--r--gcc/testsuite/gcc.target/powerpc/paired-3.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/paired-4.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/paired-5.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/paired-6.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/paired-7.c34
-rw-r--r--gcc/testsuite/gcc.target/powerpc/ppc-paired.c44
20 files changed, 1195 insertions, 19 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 99766dca081..483728dd3e6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 6665eb70370..9f6c0262cb9 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -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
index 00000000000..d01761b2ae2
--- /dev/null
+++ b/gcc/config/rs6000/750cl.h
@@ -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
index 00000000000..e70d0fa878f
--- /dev/null
+++ b/gcc/config/rs6000/paired.h
@@ -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
index 00000000000..ad3001d884c
--- /dev/null
+++ b/gcc/config/rs6000/paired.md
@@ -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")])
+
+
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 010b532993e..03660b7ff07 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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
@@ -7445,6 +7488,52 @@ altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode,
}
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)
{
rtx pat, addr;
@@ -7524,6 +7613,47 @@ spe_expand_stv_builtin (enum insn_code icode, tree exp)
}
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)
{
tree arg0 = CALL_EXPR_ARG (exp, 0);
@@ -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[] =
@@ -8237,6 +8400,78 @@ spe_expand_builtin (tree exp, rtx target, bool *expandedp)
}
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)
{
rtx pat, scratch, tmp;
@@ -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
@@ -8865,6 +9109,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)
{
const struct builtin_description *d;
@@ -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;
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 4ba955f4c82..b7dced33aad 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -56,6 +56,10 @@
#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
};
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index 4bc71128278..e3505d1e5ae 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -14568,3 +14568,4 @@
(include "altivec.md")
(include "spe.md")
(include "dfp.md")
+(include "paired.md")
diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt
index cfa123ab4b0..49800633935 100644
--- a/gcc/config/rs6000/rs6000.opt
+++ b/gcc/config/rs6000/rs6000.opt
@@ -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
diff --git a/gcc/config/rs6000/spe.md b/gcc/config/rs6000/spe.md
index b7b2fef8eab..1b66343bab2 100644
--- a/gcc/config/rs6000/spe.md
+++ b/gcc/config/rs6000/spe.md
@@ -2678,7 +2678,7 @@
(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"
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 1646df305cb..61b7f72493d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 80f20333b70..f3d9fd7a417 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 00000000000..641a8e022f8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/paired-1.c
@@ -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
index 00000000000..ef409027fd2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/paired-2.c
@@ -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
index 00000000000..756d6e111fc
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/paired-3.c
@@ -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
index 00000000000..3d5c1549bc0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/paired-4.c
@@ -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
index 00000000000..df3bb444184
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/paired-5.c
@@ -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
index 00000000000..0d6ab52e9a7
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/paired-6.c
@@ -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
index 00000000000..aa1edd033c0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/paired-7.c
@@ -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
index 00000000000..f6f3b6e5bab
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/ppc-paired.c
@@ -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;
+}
+