]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
invoke.texi: Add -maltivec, -mno-altivec, and -mabi=altivec for rs6000.
authorAldy Hernandez <aldyh@gcc.gnu.org>
Wed, 7 Nov 2001 20:49:41 +0000 (20:49 +0000)
committerAldy Hernandez <aldyh@gcc.gnu.org>
Wed, 7 Nov 2001 20:49:41 +0000 (20:49 +0000)
* doc/invoke.texi: Add -maltivec, -mno-altivec, and -mabi=altivec
for rs6000.

* config/rs6000/rs6000.h (MASK_ALTIVEC): New.
(TARGET_ALTIVEC): New.
(TARGET_SWITCHES): Add altivec.
(FIRST_PSEUDO_REGISTER): Change to 109.
(CALL_USED_REGISTERS): Same.
(FIRST_ALTIVEC_REGNO): New.
(LAST_ALTIVEC_REGNO): New.
(ALTIVEC_REGNO_P): New.
(UNITS_PER_ALTIVEC_WORD): New.
(ALTIVEC_VECTOR_MODE): New.
(FIXED_REGISTERS): Add altivec registers.
(REG_ALLOC_ORDER): Same.
(HARD_REGNO_NREGS): Adjust for altivec registers.
(HARD_REGNO_MODE_OK): Same.
(MODES_TIEABLE_P): Same.
(REGISTER_MOVE_COST): Same.
(REGNO_REG_CLASS): Same.
(reg_class): Add ALTIVEC_REGS.
(REG_CLASS_NAMES): Same.
(REG_CLASS_CONTENTS): Same.
(REG_CLASS_FROM_LETTER): Add 'v' constraint for ALTIVEC_REGS.
(ALTIVEC_ARG_RETURN): New.
(FUNCTION_VALUE): Handle VECTOR_TYPE.
(LIBCALL_VALUE): Handle altivec vector modes.
(VECTOR_MODE_SUPPORTED_P): New.
(ALTIVEC_ARG_MIN_REG): New.
(ALTIVEC_ARG_MAX_REG): New.
(ALTIVEC_ARG_NUM_REG): New.
(FUNCTION_VALUE_REGNO_P): Return true for altivec return register.
(FUNCTION_ARG_REGNO_P): Support passing args in altivec registers.
(REGISTER_NAMES): Add altivec regs.
(DEBUG_REGISTER_NAMES): Same.
(ADDITIONAL_REGISTER_NAMES): Same.
(rs6000_builtins): New.
(MD_EXPAND_BUILTIN): New.
(MD_INIT_BUILTINS): New.
(LEGITIMATE_OFFSET_ADDRESS_P): This addressing mode is not valid
for AltiVec instructions.
(LEGITIMATE_LO_SUM_ADDRESS_P): Same.
(HARD_REGNO_MODE_OK): Altivec modes can only go in altivec
registers.
(SECONDARY_MEMORY_NEEDED): We need memory to copy vector modes.
(TARGET_SWITCHES): Add no-altivec.
(DATA_ALIGNMENT): Align vectors to 128 bits.
(TARGET_OPTIONS): Add abi= option.
Add rs6000_abi_string extern.
(LOCAL_ALIGNMENT): New.
(CPP_CPU_SPEC): Define __ALTIVEC__ when -maltivec.
(MASK_ALTIVEC_ABI): New.
(TARGET_ALTIVEC_ABI): New.
(CONDITIONAL_REGISTER_USAGE): Set first 20 AltiVec registers to
call-saved.
(STACK_BOUNDARY): Adjust for altivec.
(BIGGEST_ALIGNMENT): Same.
(rs6000_args): Add vregno.
(USE_ALTIVEC_FOR_ARG_P): New.
(FIXED_REGISTERS): Add vrsave register.
(CALL_USED_REGISTERS): Same.
(CONDITIONAL_REGISTER_USAGE): Set VRSAVE info.
(VRSAVE_REGNO): New.
(reg_class): Add VRSAVE_REGS.
(REG_CLASS_NAMES): Same.
(REG_CLASS_CONTENTS): Same.
(REGNO_REG_CLASS): Same.

* config/rs6000/sysv4.h (STACK_BOUNDARY): Adjust for altivec.
(ABI_STACK_BOUNDARY): Same.
(BIGGEST_ALIGNMENT): Same.
(ADJUST_FIELD_ALIGN): Remove undef.  Define anew.
(ROUND_TYPE_ALIGN): Same.

* config/rs6000/aix.h (ROUND_TYPE_ALIGN): Change BIGGEST_ALIGNMENT
to 64.

* config/rs6000/rs6000.c (rs6000_expand_builtin): New.
(altivec_expand_builtin): New.
(altivec_init_builtins): New.
(TARGET_EXPAND_BUILTIN): New.
(TARGET_INIT_BUILTINS): New.
(rs6000_init_builtins): New.
(struct builtin_description): New.
(bdesc_2arg): New.
(rs6000_reg_names): Add altivec registers.
(alt_reg_names): Same.
(secondary_reload_class): Altivec regs can hold altivec regs and
memory.
(rs6000_emit_move): Force constants into memory for AltiVec moves.
(print_operand): Add 'y' case for printing altivec memory
operands.
(rs6000_legitimize_address): Legitimize vector addresses into
[REG+REG] or [REG].
(altivec_expand_binop_builtin): New.
New string rs6000_current_abi.
(rs6000_override_options): Call rs6000_parse_abi_options.
(rs6000_parse_abi_options): New.
(function_arg_boundary): Vector arguments must be 16
byte aligned.
(function_arg_advance): Handle vector arguments.
(function_arg_partial_nregs): Same.
(init_cumulative_args): Same.
(function_arg): Same.

* config/rs6000/rs6000.md (altivec_lvx): New.
(type): Add altivec attribute.
(movv4si): New.
(*movv4si_internal): New.
(movv16qi): New.
(*movv16qi_internal): New.
(movv8hi): New.
(*movv8hi_internal1): New.
(movv4sf): New.
(*movv4sf_internal1): New.
(altivec_stvx): New.
(vaddubm): New.
(vadduhm): New.
(vadduwm): New.
(vaddfp): New.
(vaddcuw): New.
(vaddubs): New.
(vaddsbs): New.
(vadduhs): New.
(vaddshs): New.
(vadduws): New.
(vaddsws): New.
(vand): New.
(vandc): New.
(vavgub): New.
(vavgsb): New.
(vavguh): New.
(vavgsh): New.
(vavguw): New.
(vavgsw): New.
(vcmpbfp): New.
(vcmpequb): New.
(vcmpequh): New.
(vcmpequw): New.
(vcmpeqfp): New.
(vcmpgefp): New.
(vcmpgtub): New.
(vcmpgtsb): New.
(vcmpgtuh): New.
(vcmpgtsh): New.
(vcmpgtuw): New.
(vcmpgtsw): New.
(vcmpgtfp): New.
(vcmpgefp): New.
(vcmpgtub): New.
(vcmpgtsb): New.
(vcmpgtuh): New.
(vcmpgtsh): New.
(vcmpgtuw): New.
(vcmpgtsw): New.
(vcmpgtfp): New.
(vmaxub): New.
(vmaxsb): New.
(vmaxuh): New.
(vmaxsh): New.
(vmaxuw): New.
(vmaxsw): New.
(vmaxfp): New.
(vmrghb): New.
(vmrghh): New.
(vmrghw): New.
(vmrglb): New.
(vmrglh): New.
(vmrglw): New.
(vminub): New.
(vminsb): New.
(vminuh): New.
(vminsh): New.
(vminuw): New.
(vminsw): New.
(vminfp): New.
(vmuleub): New.
(vmulesb): New.
(vmuleuh): New.
(vmulesh): New.
(vmuloub): New.
(vmulosb): New.
(vmulouh): New.
(vmulosh): New.
(vnor): New.
(vor): New.
(vpkuhum): New.
(vpkuwum): New.
(vpkpx): New.
(vpkuhss): New.
(vpkshss): New.
(vpkuwss): New.
(vpkswss): New.
(vpkuhus): New.
(vpkshus): New.
(vpkuwus): New.
(vpkswus): New.
(vrlb): New.
(vrlh): New.
(vrlw): New.
(vslb): New.
(vslh): New.
(vslw): New.
(vsl): New.
(vslo): New.
(vsrb): New.
(vrsh): New.
(vrsw): New.
(vsrab): New.
(vsrah): New.
(vsraw): New.
(vsr): New.
(vsro): New.
(vsububm): New.
(vsubuhm): New.
(vsubuwm): New.
(vsubfp): New.
(vsubcuw): New.
(vsububs): New.
(vsubsbs): New.
(vsubuhs): New.
(vsubshs): New.
(vsubuws): New.
(vsubsws): New.
(vsum4ubs): New.
(vsum4sbs): New.
(vsum4shs): New.
(vsum2sws): New.
(vsumsws): New.
(vxor): New.

From-SVN: r46833

gcc/config/rs6000/aix.h
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md
gcc/config/rs6000/sysv4.h
gcc/doc/invoke.texi

index d807ee2a9db293336e38e1d9319683e4e540ad3d..ae3b9c639077d6a214718e93e6a9fc8580c72aeb 100644 (file)
@@ -115,7 +115,7 @@ Boston, MA 02111-1307, USA.  */
     || TREE_CODE (STRUCT) == QUAL_UNION_TYPE)          \
    && TYPE_FIELDS (STRUCT) != 0                                \
    && DECL_MODE (TYPE_FIELDS (STRUCT)) == DFmode       \
-   ? MAX (MAX ((COMPUTED), (SPECIFIED)), BIGGEST_ALIGNMENT) \
+   ? MAX (MAX ((COMPUTED), (SPECIFIED)), 64)           \
    : MAX ((COMPUTED), (SPECIFIED)))
 
 
index 3c7b2c0a37011bb9478dfda13816822187575fb3..0cf9b9c46aa8426290634deb0868ed7c1eedbc38 100644 (file)
@@ -96,6 +96,9 @@ int fixuplabelno = 0;
 /* ABI enumeration available for subtarget to use.  */
 enum rs6000_abi rs6000_current_abi;
 
+/* ABI string from -mabi= option.  */
+const char *rs6000_abi_string;
+
 /* Debug flags */
 const char *rs6000_debug_name;
 int rs6000_debug_stack;                /* debug stack applications */
@@ -146,6 +149,13 @@ static int rs6000_adjust_cost PARAMS ((rtx, rtx, rtx, int));
 static int rs6000_adjust_priority PARAMS ((rtx, int));
 static int rs6000_issue_rate PARAMS ((void));
 
+static void rs6000_init_builtins PARAMS ((tree));
+static void altivec_init_builtins PARAMS ((void));
+static rtx rs6000_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
+static rtx altivec_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
+static rtx altivec_expand_binop_builtin PARAMS ((enum insn_code, tree, rtx));
+
+static void rs6000_parse_abi_options PARAMS ((void));
 \f
 /* Default register names.  */
 char rs6000_reg_names[][8] =
@@ -160,7 +170,13 @@ char rs6000_reg_names[][8] =
      "24", "25", "26", "27", "28", "29", "30", "31",
      "mq", "lr", "ctr","ap",
       "0",  "1",  "2",  "3",  "4",  "5",  "6",  "7",
-      "xer"
+      "xer",
+      /* AltiVec registers.  */
+      "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6", "v7",
+      "v8",  "v9",  "v10", "v11", "v12", "v13", "v14", "v15",
+      "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
+      "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
+      "vrsave"
 };
 
 #ifdef TARGET_REGNAMES
@@ -176,7 +192,13 @@ static const char alt_reg_names[][8] =
   "%f24",  "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",
     "mq",    "lr",  "ctr",   "ap",
   "%cr0",  "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7",
-  "xer"
+   "xer",
+   /* AltiVec registers.  */
+   "%v0",  "%v1",  "%v2",  "%v3",  "%v4",  "%v5",  "%v6", "%v7",
+   "%v8",  "%v9",  "%v10", "%v11", "%v12", "%v13", "%v14", "%v15",
+   "%v16", "%v17", "%v18", "%v19", "%v20", "%v21", "%v22", "%v23",
+   "%v24", "%v25", "%v26", "%v27", "%v28", "%v29", "%v30", "%v31",
+   "%vrsave"
 };
 #endif
 \f
@@ -205,6 +227,12 @@ static const char alt_reg_names[][8] =
 #undef TARGET_SCHED_ADJUST_PRIORITY
 #define TARGET_SCHED_ADJUST_PRIORITY rs6000_adjust_priority
 
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS rs6000_init_builtins
+
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN rs6000_expand_builtin
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 /* Override command line options.  Mostly we process the processor
@@ -438,6 +466,9 @@ rs6000_override_options (default_cpu)
        error ("Unknown -mdebug-%s switch", rs6000_debug_name);
     }
 
+  /* Handle -mabi= options.  */
+  rs6000_parse_abi_options ();
+
 #ifdef TARGET_REGNAMES
   /* If the user desires alternate register names, copy in the
      alternate names now.  */
@@ -463,6 +494,17 @@ rs6000_override_options (default_cpu)
   free_machine_status = rs6000_free_machine_status;
 }
 
+/* Handle -mabi= options.  */
+void rs6000_parse_abi_options ()
+{
+  if (rs6000_abi_string == 0)
+    return;
+  else if (! strcmp (rs6000_abi_string, "altivec"))
+    target_flags |= MASK_ALTIVEC_ABI;
+  else
+    error ("Unknown ABI specified: '%s'", rs6000_abi_string);
+}
+
 void
 optimization_options (level, size)
      int level ATTRIBUTE_UNUSED;
@@ -1544,7 +1586,7 @@ rs6000_legitimize_address (x, oldx, mode)
      rtx x;
      rtx oldx ATTRIBUTE_UNUSED;
      enum machine_mode mode;
-{ 
+{
   if (GET_CODE (x) == PLUS 
       && GET_CODE (XEXP (x, 0)) == REG
       && GET_CODE (XEXP (x, 1)) == CONST_INT
@@ -1570,6 +1612,18 @@ rs6000_legitimize_address (x, oldx, mode)
       return gen_rtx_PLUS (Pmode, XEXP (x, 0),
                           force_reg (Pmode, force_operand (XEXP (x, 1), 0)));
     }
+  else if (ALTIVEC_VECTOR_MODE (mode))
+    {
+      rtx reg;
+
+      /* Make sure both operands are registers.  */
+      if (GET_CODE (x) == PLUS)
+       return gen_rtx_PLUS (Pmode, XEXP (x, 0),
+                            force_reg (Pmode, XEXP (x, 1)));
+
+      reg = force_reg (Pmode, x);
+      return reg;
+    }
   else if (TARGET_ELF && TARGET_32BIT && TARGET_NO_TOC && ! flag_pic
           && GET_CODE (x) != CONST_INT
           && GET_CODE (x) != CONST_DOUBLE 
@@ -1887,6 +1941,15 @@ rs6000_emit_move (dest, source, mode)
        operands[1] = force_const_mem (mode, operands[1]);
       break;
       
+    case V16QImode:
+    case V8HImode:
+    case V4SFmode:
+    case V4SImode:
+      /* fixme: aldyh -- allow vector constants when they are implemented.  */
+      if (CONSTANT_P (operands[1]))
+       operands[1] = force_const_mem (mode, operands[1]);
+      break;
+      
     case SImode:
     case DImode:
       /* Use default pattern for address of ELF small data */
@@ -2087,6 +2150,7 @@ init_cumulative_args (cum, fntype, libname, incoming)
   *cum = zero_cumulative;
   cum->words = 0;
   cum->fregno = FP_ARG_MIN_REG;
+  cum->vregno = ALTIVEC_ARG_MIN_REG;
   cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
   cum->call_cookie = CALL_NORMAL;
   cum->sysv_gregno = GP_ARG_MIN_REG;
@@ -2167,6 +2231,8 @@ function_arg_boundary (mode, type)
   if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
       && (mode == DImode || mode == DFmode))
     return 64;
+  else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+    return 128;
   else
     return PARM_BOUNDARY;
 }
@@ -2184,7 +2250,14 @@ function_arg_advance (cum, mode, type, named)
 {
   cum->nargs_prototype--;
 
-  if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
+  if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+    {
+      if (cum->vregno <= ALTIVEC_ARG_MAX_REG && cum->nargs_prototype >= 0)
+       cum->vregno++;
+      else
+       cum->words += RS6000_ARG_SIZE (mode, type);
+    }
+  else if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
     {
       if (TARGET_HARD_FLOAT
          && (mode == SFmode || mode == DFmode))
@@ -2312,7 +2385,14 @@ function_arg (cum, mode, type, named)
       return GEN_INT (cum->call_cookie);
     }
 
-  if (abi == ABI_V4 || abi == ABI_SOLARIS)
+  if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+    {
+      if (cum->vregno <= ALTIVEC_ARG_MAX_REG)
+       return gen_rtx_REG (mode, cum->vregno);
+      else
+       return NULL;
+    }
+  else if (abi == ABI_V4 || abi == ABI_SOLARIS)
     {
       if (TARGET_HARD_FLOAT
          && (mode == SFmode || mode == DFmode))
@@ -2407,7 +2487,8 @@ function_arg_partial_nregs (cum, mode, type, named)
   if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
     return 0;
 
-  if (USE_FP_FOR_ARG_P (*cum, mode, type))
+  if (USE_FP_FOR_ARG_P (*cum, mode, type)
+      || USE_ALTIVEC_FOR_ARG_P (*cum, mode, type))
     {
       if (cum->nargs_prototype >= 0)
        return 0;
@@ -2863,6 +2944,476 @@ rs6000_va_arg (valist, type)
 
   return addr_rtx;
 }
+
+/* Builtins.  */
+
+#define def_builtin(MASK, NAME, TYPE, CODE)                            \
+do {                                                                   \
+  if ((MASK) & target_flags)                                           \
+    builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL);      \
+} while (0)
+
+struct builtin_description
+{
+  const unsigned int mask;
+  const enum insn_code icode;
+  const char *const name;
+  const enum rs6000_builtins code;
+};
+
+/* Simple binary operatiors: VECc = foo (VECa, VECb).  */
+static const struct builtin_description bdesc_2arg[] =
+{
+  { MASK_ALTIVEC, CODE_FOR_altivec_vaddubm, "__builtin_altivec_vaddubm", ALTIVEC_BUILTIN_VADDUBM },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vadduhm, "__builtin_altivec_vadduhm", ALTIVEC_BUILTIN_VADDUHM },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vadduwm, "__builtin_altivec_vadduwm", ALTIVEC_BUILTIN_VADDUWM },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vaddfp, "__builtin_altivec_vaddfp", ALTIVEC_BUILTIN_VADDFP },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vaddcuw, "__builtin_altivec_vaddcuw", ALTIVEC_BUILTIN_VADDCUW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vaddubs, "__builtin_altivec_vaddubs", ALTIVEC_BUILTIN_VADDUBS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vaddsbs, "__builtin_altivec_vaddsbs", ALTIVEC_BUILTIN_VADDSBS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vadduhs, "__builtin_altivec_vadduhs", ALTIVEC_BUILTIN_VADDUHS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vaddshs, "__builtin_altivec_vaddshs", ALTIVEC_BUILTIN_VADDSHS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vadduws, "__builtin_altivec_vadduws", ALTIVEC_BUILTIN_VADDUWS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vaddsws, "__builtin_altivec_vaddsws", ALTIVEC_BUILTIN_VADDSWS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vand, "__builtin_altivec_vand", ALTIVEC_BUILTIN_VAND },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vandc, "__builtin_altivec_vandc", ALTIVEC_BUILTIN_VANDC },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vavgub, "__builtin_altivec_vavgub", ALTIVEC_BUILTIN_VAVGUB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vavgsb, "__builtin_altivec_vavgsb", ALTIVEC_BUILTIN_VAVGSB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vavguh, "__builtin_altivec_vavguh", ALTIVEC_BUILTIN_VAVGUH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vavgsh, "__builtin_altivec_vavgsh", ALTIVEC_BUILTIN_VAVGSH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vavguw, "__builtin_altivec_vavguw", ALTIVEC_BUILTIN_VAVGUW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vavgsw, "__builtin_altivec_vavgsw", ALTIVEC_BUILTIN_VAVGSW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vcmpbfp, "__builtin_altivec_vcmpbfp", ALTIVEC_BUILTIN_VCMPBFP },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequb, "__builtin_altivec_vcmpequb", ALTIVEC_BUILTIN_VCMPEQUB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequh, "__builtin_altivec_vcmpequh", ALTIVEC_BUILTIN_VCMPEQUH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vcmpequw, "__builtin_altivec_vcmpequw", ALTIVEC_BUILTIN_VCMPEQUW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vcmpeqfp, "__builtin_altivec_vcmpeqfp", ALTIVEC_BUILTIN_VCMPEQFP },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgefp, "__builtin_altivec_vcmpgefp", ALTIVEC_BUILTIN_VCMPGEFP },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtub, "__builtin_altivec_vcmpgtub", ALTIVEC_BUILTIN_VCMPGTUB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsb, "__builtin_altivec_vcmpgtsb", ALTIVEC_BUILTIN_VCMPGTSB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuh, "__builtin_altivec_vcmpgtuh", ALTIVEC_BUILTIN_VCMPGTUH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsh, "__builtin_altivec_vcmpgtsh", ALTIVEC_BUILTIN_VCMPGTSH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtuw, "__builtin_altivec_vcmpgtuw", ALTIVEC_BUILTIN_VCMPGTUW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtsw, "__builtin_altivec_vcmpgtsw", ALTIVEC_BUILTIN_VCMPGTSW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vcmpgtfp, "__builtin_altivec_vcmpgtfp", ALTIVEC_BUILTIN_VCMPGTFP },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmaxub, "__builtin_altivec_vmaxub", ALTIVEC_BUILTIN_VMAXUB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmaxsb, "__builtin_altivec_vmaxsb", ALTIVEC_BUILTIN_VMAXSB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmaxuh, "__builtin_altivec_vmaxuh", ALTIVEC_BUILTIN_VMAXUH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmaxsh, "__builtin_altivec_vmaxsh", ALTIVEC_BUILTIN_VMAXSH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmaxuw, "__builtin_altivec_vmaxuw", ALTIVEC_BUILTIN_VMAXUW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmaxsw, "__builtin_altivec_vmaxsw", ALTIVEC_BUILTIN_VMAXSW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmaxfp, "__builtin_altivec_vmaxfp", ALTIVEC_BUILTIN_VMAXFP },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmrghb, "__builtin_altivec_vmrghb", ALTIVEC_BUILTIN_VMRGHB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmrghh, "__builtin_altivec_vmrghh", ALTIVEC_BUILTIN_VMRGHH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmrghw, "__builtin_altivec_vmrghw", ALTIVEC_BUILTIN_VMRGHW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmrglb, "__builtin_altivec_vmrglb", ALTIVEC_BUILTIN_VMRGLB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmrglh, "__builtin_altivec_vmrglh", ALTIVEC_BUILTIN_VMRGLH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmrglw, "__builtin_altivec_vmrglw", ALTIVEC_BUILTIN_VMRGLW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vminub, "__builtin_altivec_vminub", ALTIVEC_BUILTIN_VMINUB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vminsb, "__builtin_altivec_vminsb", ALTIVEC_BUILTIN_VMINSB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vminuh, "__builtin_altivec_vminuh", ALTIVEC_BUILTIN_VMINUH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vminsh, "__builtin_altivec_vminsh", ALTIVEC_BUILTIN_VMINSH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vminuw, "__builtin_altivec_vminuw", ALTIVEC_BUILTIN_VMINUW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vminsw, "__builtin_altivec_vminsw", ALTIVEC_BUILTIN_VMINSW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vminfp, "__builtin_altivec_vminfp", ALTIVEC_BUILTIN_VMINFP },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmuleub, "__builtin_altivec_vmuleub", ALTIVEC_BUILTIN_VMULEUB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmulesb, "__builtin_altivec_vmulesb", ALTIVEC_BUILTIN_VMULESB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmuleuh, "__builtin_altivec_vmuleuh", ALTIVEC_BUILTIN_VMULEUH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmulesh, "__builtin_altivec_vmulesh", ALTIVEC_BUILTIN_VMULESH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmuloub, "__builtin_altivec_vmuloub", ALTIVEC_BUILTIN_VMULOUB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmulosb, "__builtin_altivec_vmulosb", ALTIVEC_BUILTIN_VMULOSB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh", ALTIVEC_BUILTIN_VMULOUH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vmulosh, "__builtin_altivec_vmulosh", ALTIVEC_BUILTIN_VMULOSH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vnor, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vor, "__builtin_altivec_vor", ALTIVEC_BUILTIN_VOR },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum, "__builtin_altivec_vpkuhum", ALTIVEC_BUILTIN_VPKUHUM },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum, "__builtin_altivec_vpkuwum", ALTIVEC_BUILTIN_VPKUWUM },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vpkpx, "__builtin_altivec_vpkpx", ALTIVEC_BUILTIN_VPKPX },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhss, "__builtin_altivec_vpkuhss", ALTIVEC_BUILTIN_VPKUHSS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vpkshss, "__builtin_altivec_vpkshss", ALTIVEC_BUILTIN_VPKSHSS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwss, "__builtin_altivec_vpkuwss", ALTIVEC_BUILTIN_VPKUWSS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vpkswss, "__builtin_altivec_vpkswss", ALTIVEC_BUILTIN_VPKSWSS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhus, "__builtin_altivec_vpkuhus", ALTIVEC_BUILTIN_VPKUHUS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vpkshus, "__builtin_altivec_vpkshus", ALTIVEC_BUILTIN_VPKSHUS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwus, "__builtin_altivec_vpkuwus", ALTIVEC_BUILTIN_VPKUWUS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vpkswus, "__builtin_altivec_vpkswus", ALTIVEC_BUILTIN_VPKSWUS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vrlb, "__builtin_altivec_vrlb", ALTIVEC_BUILTIN_VRLB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vrlh, "__builtin_altivec_vrlh", ALTIVEC_BUILTIN_VRLH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vrlw, "__builtin_altivec_vrlw", ALTIVEC_BUILTIN_VRLW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vslb, "__builtin_altivec_vslb", ALTIVEC_BUILTIN_VSLB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vslh, "__builtin_altivec_vslh", ALTIVEC_BUILTIN_VSLH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vslw, "__builtin_altivec_vslw", ALTIVEC_BUILTIN_VSLW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsl, "__builtin_altivec_vsl", ALTIVEC_BUILTIN_VSL },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vslo, "__builtin_altivec_vslo", ALTIVEC_BUILTIN_VSLO },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsrb, "__builtin_altivec_vsrb", ALTIVEC_BUILTIN_VSRB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vrsh, "__builtin_altivec_vrsh", ALTIVEC_BUILTIN_VRSH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vrsw, "__builtin_altivec_vrsw", ALTIVEC_BUILTIN_VRSW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsrab, "__builtin_altivec_vsrab", ALTIVEC_BUILTIN_VSRAB },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsrah, "__builtin_altivec_vsrah", ALTIVEC_BUILTIN_VSRAH },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsraw, "__builtin_altivec_vsraw", ALTIVEC_BUILTIN_VSRAW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsr, "__builtin_altivec_vsr", ALTIVEC_BUILTIN_VSR },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsro, "__builtin_altivec_vsro", ALTIVEC_BUILTIN_VSRO },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsububm, "__builtin_altivec_vsububm", ALTIVEC_BUILTIN_VSUBUBM },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsubuhm, "__builtin_altivec_vsubuhm", ALTIVEC_BUILTIN_VSUBUHM },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsubuwm, "__builtin_altivec_vsubuwm", ALTIVEC_BUILTIN_VSUBUWM },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsubfp, "__builtin_altivec_vsubfp", ALTIVEC_BUILTIN_VSUBFP },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsubcuw, "__builtin_altivec_vsubcuw", ALTIVEC_BUILTIN_VSUBCUW },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsububs, "__builtin_altivec_vsububs", ALTIVEC_BUILTIN_VSUBUBS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsubsbs, "__builtin_altivec_vsubsbs", ALTIVEC_BUILTIN_VSUBSBS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsubuhs, "__builtin_altivec_vsubuhs", ALTIVEC_BUILTIN_VSUBUHS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsubshs, "__builtin_altivec_vsubshs", ALTIVEC_BUILTIN_VSUBSHS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsubuws, "__builtin_altivec_vsubuws", ALTIVEC_BUILTIN_VSUBUWS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsubsws, "__builtin_altivec_vsubsws", ALTIVEC_BUILTIN_VSUBSWS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsum4ubs, "__builtin_altivec_vsum4ubs", ALTIVEC_BUILTIN_VSUM4UBS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsum4sbs, "__builtin_altivec_vsum4sbs", ALTIVEC_BUILTIN_VSUM4SBS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsum4shs, "__builtin_altivec_vsum4shs", ALTIVEC_BUILTIN_VSUM4SHS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsum2sws, "__builtin_altivec_vsum2sws", ALTIVEC_BUILTIN_VSUM2SWS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vsumsws, "__builtin_altivec_vsumsws", ALTIVEC_BUILTIN_VSUMSWS },
+  { MASK_ALTIVEC, CODE_FOR_altivec_vxor, "__builtin_altivec_vxor", ALTIVEC_BUILTIN_VXOR },
+};
+
+static rtx
+altivec_expand_binop_builtin (icode, arglist, target)
+     enum insn_code icode;
+     tree arglist;
+     rtx target;
+{
+  rtx pat;
+  tree arg0 = TREE_VALUE (arglist);
+  tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+  rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+  rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+  enum machine_mode tmode = insn_data[icode].operand[0].mode;
+  enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+  enum machine_mode mode1 = insn_data[icode].operand[2].mode;
+
+  if (! target
+      || GET_MODE (target) != tmode
+      || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+    target = gen_reg_rtx (tmode);
+
+  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);
+
+  pat = GEN_FCN (icode) (target, op0, op1);
+  if (! pat)
+    return 0;
+  emit_insn (pat);
+
+  return target;
+}
+
+static rtx
+altivec_expand_builtin (exp, target, subtarget, mode, ignore)
+     tree exp;
+     rtx target;
+     rtx subtarget;
+     enum machine_mode mode;
+     int ignore;
+{
+  struct builtin_description *d;
+  size_t i;
+  enum insn_code icode;
+  tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+  tree arglist = TREE_OPERAND (exp, 1);
+  tree arg0, arg1, arg2, arg3;
+  rtx op0, op1, op2, pat;
+  enum machine_mode tmode, mode0, mode1, mode2;
+  unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+  
+  switch (fcode)
+    {
+    case ALTIVEC_BUILTIN_LD_INTERNAL:
+      icode = CODE_FOR_altivec_lvx;
+      arg0 = TREE_VALUE (arglist);
+      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+      tmode = insn_data[icode].operand[0].mode;
+      mode0 = insn_data[icode].operand[1].mode;
+
+      if (! target
+         || GET_MODE (target) != tmode
+         || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+       target = gen_reg_rtx (tmode);
+
+      if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+       op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
+
+      pat = GEN_FCN (icode) (target, op0);
+      if (! pat)
+       return 0;
+      emit_insn (pat);
+      return target;
+
+    case ALTIVEC_BUILTIN_ST_INTERNAL:
+      icode = CODE_FOR_altivec_stvx;
+      arg0 = TREE_VALUE (arglist);
+      arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+      op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+      mode0 = insn_data[icode].operand[0].mode;
+      mode1 = insn_data[icode].operand[1].mode;
+
+      if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
+       op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
+      if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
+       op1 = copy_to_mode_reg (mode1, op1);
+
+      pat = GEN_FCN (icode) (op0, op1);
+      if (! pat)
+       return 0;
+      emit_insn (pat);
+      return NULL_RTX;
+    }
+
+  /* Handle simple binary operations.  */
+  for (i = 0, d = bdesc_2arg; i < sizeof (bdesc_2arg) / sizeof *d; i++, d++)
+    if (d->code == fcode)
+      return altivec_expand_binop_builtin (d->icode, arglist, target);
+
+  abort ();
+  return NULL_RTX;
+}
+
+/* Expand an expression EXP that calls a built-in function,
+   with result going to TARGET if that's convenient
+   (and in mode MODE if that's convenient).
+   SUBTARGET may be used as the target for computing one of EXP's operands.
+   IGNORE is nonzero if the value is to be ignored.  */
+
+static rtx
+rs6000_expand_builtin (exp, target, subtarget, mode, ignore)
+     tree exp;
+     rtx target;
+     rtx subtarget;
+     enum machine_mode mode;
+     int ignore;
+{
+  if (TARGET_ALTIVEC)
+    return altivec_expand_builtin (exp, target, subtarget, mode, ignore);
+
+  abort ();
+}
+
+static void
+rs6000_init_builtins (list_node)
+     tree list_node ATTRIBUTE_UNUSED;
+{
+  if (TARGET_ALTIVEC)
+    altivec_init_builtins ();
+}
+
+static void
+altivec_init_builtins (void)
+{
+  struct builtin_description * d;
+  size_t i;
+
+  tree endlink = void_list_node;
+
+  tree pint_type_node = build_pointer_type (integer_type_node);
+
+  /* V4SI foo (int *).  */
+  tree v4si_ftype_pint
+    = build_function_type (V4SI_type_node,
+                          tree_cons (NULL_TREE, pint_type_node, endlink));
+
+  /* void foo (int *, V4SI).  */
+  tree void_ftype_pint_v4si
+    = build_function_type (void_type_node,
+                          tree_cons (NULL_TREE, pint_type_node,
+                                     tree_cons (NULL_TREE, V4SI_type_node,
+                                                endlink)));
+
+  tree v4si_ftype_v4si_v4si
+    = build_function_type (V4SI_type_node,
+                          tree_cons (NULL_TREE, V4SI_type_node,
+                                     tree_cons (NULL_TREE, V4SI_type_node,
+                                                endlink)));
+
+  tree v4sf_ftype_v4sf_v4sf
+    = build_function_type (V4SF_type_node,
+                          tree_cons (NULL_TREE, V4SF_type_node,
+                                     tree_cons (NULL_TREE, V4SF_type_node,
+                                                endlink)));
+
+  tree v8hi_ftype_v8hi_v8hi
+    = build_function_type (V8HI_type_node,
+                          tree_cons (NULL_TREE, V8HI_type_node,
+                                     tree_cons (NULL_TREE, V8HI_type_node,
+                                                endlink)));
+
+  tree v16qi_ftype_v16qi_v16qi
+    = build_function_type (V16QI_type_node,
+                          tree_cons (NULL_TREE, V16QI_type_node,
+                                     tree_cons (NULL_TREE, V16QI_type_node,
+                                                endlink)));
+
+  tree v4si_ftype_v4sf_v4sf
+    = build_function_type (V4SI_type_node,
+                          tree_cons (NULL_TREE, V4SF_type_node,
+                                     tree_cons (NULL_TREE, V4SF_type_node,
+                                                endlink)));
+
+  tree v8hi_ftype_v16qi_v16qi
+    = build_function_type (V8HI_type_node,
+                          tree_cons (NULL_TREE, V16QI_type_node,
+                                     tree_cons (NULL_TREE, V16QI_type_node,
+                                                endlink)));
+
+  tree v4si_ftype_v8hi_v8hi
+    = build_function_type (V4SI_type_node,
+                          tree_cons (NULL_TREE, V8HI_type_node,
+                                     tree_cons (NULL_TREE, V8HI_type_node,
+                                                endlink)));
+
+  tree v8hi_ftype_v4si_v4si
+    = build_function_type (V8HI_type_node,
+                          tree_cons (NULL_TREE, V4SI_type_node,
+                                     tree_cons (NULL_TREE, V4SI_type_node,
+                                                endlink)));
+
+  tree v16qi_ftype_v8hi_v8hi
+    = build_function_type (V16QI_type_node,
+                          tree_cons (NULL_TREE, V8HI_type_node,
+                                     tree_cons (NULL_TREE, V8HI_type_node,
+                                                endlink)));
+
+  tree v4si_ftype_v16qi_v4si
+    = build_function_type (V4SI_type_node,
+                          tree_cons (NULL_TREE, V16QI_type_node,
+                                     tree_cons (NULL_TREE, V4SI_type_node,
+                                                endlink)));
+
+  tree v4si_ftype_v8hi_v4si
+    = build_function_type (V4SI_type_node,
+                          tree_cons (NULL_TREE, V8HI_type_node,
+                                     tree_cons (NULL_TREE, V4SI_type_node,
+                                                endlink)));
+
+  tree int_ftype_v4si_v4si
+    = build_function_type (integer_type_node,
+                          tree_cons (NULL_TREE, V4SI_type_node,
+                                     tree_cons (NULL_TREE, V4SI_type_node,
+                                                endlink)));
+
+  tree int_ftype_v4sf_v4sf
+    = build_function_type (integer_type_node,
+                          tree_cons (NULL_TREE, V4SF_type_node,
+                                     tree_cons (NULL_TREE, V4SF_type_node,
+                                                endlink)));
+
+  tree int_ftype_v16qi_v16qi
+    = build_function_type (integer_type_node,
+                          tree_cons (NULL_TREE, V16QI_type_node,
+                                     tree_cons (NULL_TREE, V16QI_type_node,
+                                                endlink)));
+
+  tree int_ftype_v8hi_v8hi
+    = build_function_type (integer_type_node,
+                          tree_cons (NULL_TREE, V8HI_type_node,
+                                     tree_cons (NULL_TREE, V8HI_type_node,
+                                                endlink)));
+
+  def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal", v4si_ftype_pint, ALTIVEC_BUILTIN_LD_INTERNAL);
+  def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal", void_ftype_pint_v4si, ALTIVEC_BUILTIN_ST_INTERNAL);
+
+  /* Add the simple binary operators.  */
+  for (i = 0, d = bdesc_2arg; i < sizeof (bdesc_2arg) / sizeof *d; i++, d++)
+    {
+      enum machine_mode mode0, mode1, mode2;
+      tree type;
+
+      if (d->name == 0)
+       continue;
+      
+      mode0 = insn_data[d->icode].operand[0].mode;
+      mode1 = insn_data[d->icode].operand[1].mode;
+      mode2 = insn_data[d->icode].operand[2].mode;
+
+      /* When all three operands are of the same mode.  */
+      if (mode0 == mode1 && mode1 == mode2)
+       {
+         switch (mode0)
+           {
+           case V4SFmode:
+             type = v4sf_ftype_v4sf_v4sf;
+             break;
+           case V4SImode:
+             type = v4si_ftype_v4si_v4si;
+             break;
+           case V16QImode:
+             type = v16qi_ftype_v16qi_v16qi;
+             break;
+           case V8HImode:
+             type = v8hi_ftype_v8hi_v8hi;
+             break;
+           default:
+             abort ();
+           }
+       }
+
+      /* A few other combos we really don't want to do manually.  */
+
+      /* vint, vfloat, vfloat.  */
+      else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == V4SFmode)
+       type = v4si_ftype_v4sf_v4sf;
+
+      /* vshort, vchar, vchar.  */
+      else if (mode0 == V8HImode && mode1 == V16QImode && mode2 == V16QImode)
+       type = v8hi_ftype_v16qi_v16qi;
+
+      /* vint, vshort, vshort.  */
+      else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode)
+       type = v4si_ftype_v8hi_v8hi;
+
+      /* vshort, vint, vint.  */
+      else if (mode0 == V8HImode && mode1 == V4SImode && mode2 == V4SImode)
+       type = v8hi_ftype_v4si_v4si;
+
+      /* vchar, vshort, vshort.  */
+      else if (mode0 == V16QImode && mode1 == V8HImode && mode2 == V8HImode)
+       type = v16qi_ftype_v8hi_v8hi;
+
+      /* vint, vchar, vint.  */
+      else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V4SImode)
+       type = v4si_ftype_v16qi_v4si;
+
+      /* vint, vshort, vint.  */
+      else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V4SImode)
+       type = v4si_ftype_v8hi_v4si;
+
+      /* fixme: aldyh */
+      /* int, x, x.  */
+      else if (mode0 == SImode)
+       {
+         switch (mode1)
+           {
+           case V4SImode:
+             type = int_ftype_v4si_v4si;
+             break;
+           case V4SFmode:
+             type = int_ftype_v4sf_v4sf;
+             break;
+           case V16QImode:
+             type = int_ftype_v16qi_v16qi;
+             break;
+           case V8HImode:
+             type = int_ftype_v8hi_v8hi;
+             break;
+           default:
+             abort ();
+           }
+       }
+
+      else
+       abort ();
+
+      def_builtin (d->mask, d->name, type, d->code);
+    }
+}
+
 \f
 /* Generate a memory reference for expand_block_move, copying volatile,
    and other bits from an original memory reference.  */
@@ -3966,6 +4517,11 @@ secondary_reload_class (class, mode, in)
       && (class == FLOAT_REGS || class == NON_SPECIAL_REGS))
     return NO_REGS;
 
+  /* Memory, and AltiVec registers can go into AltiVec registers.  */
+  if ((regno == -1 || ALTIVEC_REGNO_P (regno))
+      && class == ALTIVEC_REGS)
+    return NO_REGS;
+
   /* We can copy among the CR registers.  */
   if ((class == CR_REGS || class == CR0_REGS)
       && regno >= 0 && CR_REGNO_P (regno))
@@ -4739,6 +5295,32 @@ print_operand (file, x, code)
                     reg_names[SMALL_DATA_REG]);
        }
       return;
+
+      /* Print AltiVec memory operand.  */
+    case 'y':
+      {
+       rtx tmp;
+
+       if (GET_CODE (x) != MEM)
+         abort ();
+
+       tmp = XEXP (x, 0);
+
+       if (GET_CODE (tmp) == REG)
+         fprintf (file, "0, %s", reg_names[REGNO (tmp)]);
+       else if (GET_CODE (tmp) == PLUS && GET_CODE (XEXP (tmp, 1)) == REG)
+         {
+           if (REGNO (XEXP (tmp, 0)) == 0)
+             fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (tmp, 1)) ],
+                      reg_names[ REGNO (XEXP (tmp, 0)) ]);
+           else
+             fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (tmp, 0)) ],
+                      reg_names[ REGNO (XEXP (tmp, 1)) ]);
+         }
+       else
+         abort ();
+       break;
+      }
                            
     case 0:
       if (GET_CODE (x) == REG)
index 47b97c73e7b83a9d43afeb879cbfeb3885d72a95..a5fa10b5b27ef6dc75e65369b6212b869587a998 100644 (file)
@@ -83,7 +83,8 @@ Boston, MA 02111-1307, USA.  */
 %{mcpu=801: -D_ARCH_PPC} \
 %{mcpu=821: -D_ARCH_PPC} \
 %{mcpu=823: -D_ARCH_PPC} \
-%{mcpu=860: -D_ARCH_PPC}"
+%{mcpu=860: -D_ARCH_PPC} \
+%{maltivec: -D__ALTIVEC__}"
 
 /* Common ASM definitions used by ASM_SPEC among the various targets
    for handling -mcpu=xxx switches.  */
@@ -209,6 +210,12 @@ extern int target_flags;
 /* Nonzero if we need to schedule the prolog and epilog.  */
 #define MASK_SCHED_PROLOG      0x00040000
 
+/* Use AltiVec instructions.  */
+#define MASK_ALTIVEC           0x00080000
+
+/* Enhance the current ABI with AltiVec extensions.  */
+#define MASK_ALTIVEC_ABI       0x00100000
+
 #define TARGET_POWER           (target_flags & MASK_POWER)
 #define TARGET_POWER2          (target_flags & MASK_POWER2)
 #define TARGET_POWERPC         (target_flags & MASK_POWERPC)
@@ -227,6 +234,8 @@ extern int target_flags;
 #define TARGET_NO_UPDATE       (target_flags & MASK_NO_UPDATE)
 #define TARGET_NO_FUSED_MADD   (target_flags & MASK_NO_FUSED_MADD)
 #define TARGET_SCHED_PROLOG    (target_flags & MASK_SCHED_PROLOG)
+#define TARGET_ALTIVEC         (target_flags & MASK_ALTIVEC)
+#define TARGET_ALTIVEC_ABI     (target_flags & MASK_ALTIVEC_ABI)
 
 #define TARGET_32BIT           (! TARGET_64BIT)
 #define TARGET_HARD_FLOAT      (! TARGET_SOFT_FLOAT)
@@ -282,6 +291,10 @@ extern int target_flags;
                        N_("Use PowerPC-64 instruction set")},          \
   {"no-powerpc64",     - MASK_POWERPC64,                               \
                        N_("Don't use PowerPC-64 instruction set")},    \
+  {"altivec",          MASK_ALTIVEC,                                   \
+                       N_("Use AltiVec instructions.")},               \
+  {"no-altivec",       - MASK_ALTIVEC,                                 \
+                       N_("Don't use AltiVec instructions.")}, \
   {"new-mnemonics",    MASK_NEW_MNEMONICS,                             \
                        N_("Use new mnemonics for PowerPC architecture")},\
   {"old-mnemonics",    -MASK_NEW_MNEMONICS,                            \
@@ -409,6 +422,7 @@ extern enum processor_type rs6000_cpu;
    {"tune=", &rs6000_select[2].string,                                 \
     N_("Schedule code for given CPU") },                               \
    {"debug=", &rs6000_debug_name, N_("Enable debug output") },         \
+   {"abi=", &rs6000_abi_string, N_("Specify ABI to use") },            \
    SUBTARGET_OPTIONS                                                   \
 }
 
@@ -424,7 +438,8 @@ struct rs6000_cpu_select
 extern struct rs6000_cpu_select rs6000_select[];
 
 /* Debug support */
-extern const char *rs6000_debug_name;          /* Name for -mdebug-xxxx option */
+extern const char *rs6000_debug_name;  /* Name for -mdebug-xxxx option */
+extern const char *rs6000_abi_string;  /* for -mabi={sysv,darwin,solaris,eabi,aix,altivec} */
 extern int rs6000_debug_stack;         /* debug stack applications */
 extern int rs6000_debug_arg;           /* debug argument handling */
 
@@ -505,6 +520,7 @@ extern int rs6000_debug_arg;                /* debug argument handling */
 #define UNITS_PER_WORD (! TARGET_POWERPC64 ? 4 : 8)
 #define MIN_UNITS_PER_WORD 4
 #define UNITS_PER_FP_WORD 8
+#define UNITS_PER_ALTIVEC_WORD 16
 
 /* Type used for ptrdiff_t, as a string used in a declaration.  */
 #define PTRDIFF_TYPE "int"
@@ -569,13 +585,20 @@ extern int rs6000_debug_arg;              /* debug argument handling */
 #define PARM_BOUNDARY (TARGET_32BIT ? 32 : 64)
 
 /* Boundary (in *bits*) on which stack pointer should be aligned.  */
-#define STACK_BOUNDARY (TARGET_32BIT ? 64 : 128)
+#define STACK_BOUNDARY ((TARGET_32BIT && !TARGET_ALTIVEC_ABI) ? 64 : 128)
 
 /* Allocation boundary (in *bits*) for the code of a function.  */
 #define FUNCTION_BOUNDARY 32
 
 /* No data type wants to be aligned rounder than this.  */
-#define BIGGEST_ALIGNMENT 64
+#define BIGGEST_ALIGNMENT 128
+
+/* A C expression to compute the alignment for a variables in the
+   local store.  TYPE is the data type, and ALIGN is the alignment
+   that the object would ordinarily have.  */
+#define LOCAL_ALIGNMENT(TYPE, ALIGN)                           \
+       ((TARGET_ALTIVEC                                        \
+         && TREE_CODE (TYPE)) == VECTOR_TYPE ? 128 : ALIGN)
 
 /* Handle #pragma pack.  */
 #define HANDLE_PRAGMA_PACK 1
@@ -594,9 +617,11 @@ extern int rs6000_debug_arg;               /* debug argument handling */
   (TREE_CODE (EXP) == STRING_CST       \
    && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
 
-/* Make arrays of chars word-aligned for the same reasons.  */
+/* Make arrays of chars word-aligned for the same reasons.
+   Align vectors to 128 bits.  */
 #define DATA_ALIGNMENT(TYPE, ALIGN)            \
-  (TREE_CODE (TYPE) == ARRAY_TYPE              \
+  (TREE_CODE (TYPE) == VECTOR_TYPE ? 128       \
+   : TREE_CODE (TYPE) == ARRAY_TYPE            \
    && TYPE_MODE (TREE_TYPE (TYPE)) == QImode   \
    && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
 
@@ -634,10 +659,12 @@ extern int rs6000_debug_arg;              /* debug argument handling */
    a register, in order to work around problems in allocating stack storage
    in inline functions.  */
 
-#define FIRST_PSEUDO_REGISTER 77
+#define FIRST_PSEUDO_REGISTER 110
 
 /* This must not decrease, for backwards compatibility.  If
    FIRST_PSEUDO_REGISTER increases, this should as well.  */
+/* fixme: this needs to be defined to "TARGET_ALTIVEC_ABI ? 110 : 77"
+   and then fix usages of DWARF_FRAME_REGISTERS to work.  */
 #define DWARF_FRAME_REGISTERS 77
 
 /* 1 for registers that have pervasive standard uses
@@ -655,7 +682,12 @@ extern int rs6000_debug_arg;               /* debug argument handling */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-   0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1}
+   0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1,         \
+   /* AltiVec registers.  */                      \
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+   0                                              \
+}
 
 /* 1 for registers not available across function calls.
    These must include the FIXED_REGISTERS and also any
@@ -669,7 +701,13 @@ extern int rs6000_debug_arg;               /* debug argument handling */
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, \
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-   1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1}
+   1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1,         \
+   /* AltiVec registers.  */                      \
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+   0                                              \
+}
+
 
 #define MQ_REGNO     64
 #define CR0_REGNO    68
@@ -679,6 +717,9 @@ extern int rs6000_debug_arg;                /* debug argument handling */
 #define CR4_REGNO    72
 #define MAX_CR_REGNO 75
 #define XER_REGNO    76
+#define FIRST_ALTIVEC_REGNO    77
+#define LAST_ALTIVEC_REGNO     108
+#define VRSAVE_REGNO           109
 
 /* List the order in which to allocate registers.  Each register must be
    listed once, even those in FIXED_REGISTERS.
@@ -701,7 +742,16 @@ extern int rs6000_debug_arg;               /* debug argument handling */
        mq              (not saved; best to use it if we can)
        ctr             (not saved; when we have the choice ctr is better)
        lr              (saved)
-        cr5, r1, r2, ap, xer (fixed)  */
+        cr5, r1, r2, ap, xer, vrsave (fixed)
+
+       AltiVec registers:
+       v0 - v1         (not saved or used for anything)
+       v13 - v3        (not saved; incoming vector arg registers)
+       v2              (not saved; incoming vector arg reg; return value)
+       v19 - v14       (not saved or used for anything)
+       v31 - v20       (saved; order given to save least number)
+*/
+                                               
 
 #define REG_ALLOC_ORDER                                        \
   {32,                                                         \
@@ -716,7 +766,14 @@ extern int rs6000_debug_arg;               /* debug argument handling */
    31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \
    18, 17, 16, 15, 14, 13, 12,                         \
    64, 66, 65,                                                 \
-   73, 1, 2, 67, 76}
+   73, 1, 2, 67, 76,                                   \
+   /* AltiVec registers.  */                           \
+   77, 78,                                             \
+   90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80,         \
+   79,                                                 \
+   96, 95, 94, 93, 92, 91,                             \
+   108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97 \
+}
 
 /* True if register is floating-point.  */
 #define FP_REGNO_P(N) ((N) >= 32 && (N) <= 63)
@@ -733,6 +790,9 @@ extern int rs6000_debug_arg;                /* debug argument handling */
 /* True if register is the XER register.  */
 #define XER_REGNO_P(N) ((N) == XER_REGNO)
 
+/* True if register is an AltiVec register.  */
+#define ALTIVEC_REGNO_P(N) ((N) >= FIRST_ALTIVEC_REGNO && (N) <= LAST_ALTIVEC_REGNO)
+
 /* Return number of consecutive hard regs needed starting at reg REGNO
    to hold something of mode MODE.
    This is ordinarily the length in words of a value of mode MODE
@@ -744,8 +804,23 @@ extern int rs6000_debug_arg;               /* debug argument handling */
 #define HARD_REGNO_NREGS(REGNO, MODE)                                  \
   (FP_REGNO_P (REGNO)                                                  \
    ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
+   : ALTIVEC_REGNO_P (REGNO)                                           \
+   ? ((GET_MODE_SIZE (MODE) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD) \
    : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
 
+#define ALTIVEC_VECTOR_MODE(MODE)      \
+       ((MODE) == V16QImode            \
+        || (MODE) == V8HImode          \
+        || (MODE) == V4SFmode          \
+        || (MODE) == V4SImode)
+
+/* Define this macro to be nonzero if the port is prepared to handle
+   insns involving vector mode MODE.  At the very least, it must have
+   move patterns for this mode.  */
+
+#define VECTOR_MODE_SUPPORTED_P(MODE)  \
+       (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (MODE))
+
 /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
    For POWER and PowerPC, the GPRs can hold any mode, but the float
    registers only can hold floating modes and DImode, and CR register only
@@ -757,6 +832,7 @@ extern int rs6000_debug_arg;                /* debug argument handling */
    (GET_MODE_CLASS (MODE) == MODE_FLOAT                                        \
     || (GET_MODE_CLASS (MODE) == MODE_INT                              \
        && GET_MODE_SIZE (MODE) == UNITS_PER_FP_WORD))                  \
+   : ALTIVEC_REGNO_P (REGNO) ? ALTIVEC_VECTOR_MODE (MODE)              \
    : CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC             \
    : XER_REGNO_P (REGNO) ? (MODE) == PSImode                           \
    : ! INT_REGNO_P (REGNO) ? (GET_MODE_CLASS (MODE) == MODE_INT                \
@@ -776,6 +852,10 @@ extern int rs6000_debug_arg;               /* debug argument handling */
    ? GET_MODE_CLASS (MODE2) == MODE_CC         \
    : GET_MODE_CLASS (MODE2) == MODE_CC         \
    ? GET_MODE_CLASS (MODE1) == MODE_CC         \
+   : ALTIVEC_VECTOR_MODE (MODE1)               \
+   ? ALTIVEC_VECTOR_MODE (MODE2)               \
+   : ALTIVEC_VECTOR_MODE (MODE2)               \
+   ? ALTIVEC_VECTOR_MODE (MODE1)               \
    : 1)
 
 /* A C expression returning the cost of moving data from a register of class
@@ -785,9 +865,11 @@ extern int rs6000_debug_arg;               /* debug argument handling */
    registers is expensive.  */
 
 #define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2)               \
-   ((CLASS1) == FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 2               \
+   ((CLASS1) == FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 2       \
    : (CLASS1) == FLOAT_REGS && (CLASS2) != FLOAT_REGS ? 10     \
    : (CLASS1) != FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 10     \
+   : (CLASS1) == ALTIVEC_REGS && (CLASS2) != ALTIVEC_REGS ? 20 \
+   : (CLASS1) != ALTIVEC_REGS && (CLASS2) == ALTIVEC_REGS ? 20 \
    : (((CLASS1) == SPECIAL_REGS || (CLASS1) == MQ_REGS         \
        || (CLASS1) == LINK_REGS || (CLASS1) == CTR_REGS                \
        || (CLASS1) == LINK_OR_CTR_REGS)                                \
@@ -839,6 +921,12 @@ extern int rs6000_debug_arg;               /* debug argument handling */
     global_regs[PIC_OFFSET_TABLE_REGNUM]                               \
       = fixed_regs[PIC_OFFSET_TABLE_REGNUM]                            \
         = call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;                 \
+  if (TARGET_ALTIVEC_ABI)                                              \
+    {                                                                  \
+      fixed_regs[VRSAVE_REGNO] = call_used_regs[VRSAVE_REGNO] = 1;     \
+      for (i = FIRST_ALTIVEC_REGNO; i < FIRST_ALTIVEC_REGNO + 20; ++i) \
+        call_used_regs[i] = 1;                                         \
+    }                                                                  \
 }
 
 /* Specify the registers used for certain standard purposes.
@@ -912,6 +1000,8 @@ enum reg_class
   BASE_REGS,
   GENERAL_REGS,
   FLOAT_REGS,
+  ALTIVEC_REGS,
+  VRSAVE_REGS,
   NON_SPECIAL_REGS,
   MQ_REGS,
   LINK_REGS,
@@ -937,6 +1027,8 @@ enum reg_class
   "BASE_REGS",                                                         \
   "GENERAL_REGS",                                                      \
   "FLOAT_REGS",                                                                \
+  "ALTIVEC_REGS",                                                      \
+  "VRSAVE_REGS",                                                       \
   "NON_SPECIAL_REGS",                                                  \
   "MQ_REGS",                                                           \
   "LINK_REGS",                                                         \
@@ -955,24 +1047,26 @@ enum reg_class
    This is an initializer for a vector of HARD_REG_SET
    of length N_REG_CLASSES.  */
 
-#define REG_CLASS_CONTENTS                                             \
-{                                                                      \
-  { 0x00000000, 0x00000000, 0x00000000 },      /* NO_REGS */           \
-  { 0xfffffffe, 0x00000000, 0x00000008 },      /* BASE_REGS */         \
-  { 0xffffffff, 0x00000000, 0x00000008 },      /* GENERAL_REGS */      \
-  { 0x00000000, 0xffffffff, 0x00000000 },      /* FLOAT_REGS */        \
-  { 0xffffffff, 0xffffffff, 0x00000008 },      /* NON_SPECIAL_REGS */  \
-  { 0x00000000, 0x00000000, 0x00000001 },      /* MQ_REGS */           \
-  { 0x00000000, 0x00000000, 0x00000002 },      /* LINK_REGS */         \
-  { 0x00000000, 0x00000000, 0x00000004 },      /* CTR_REGS */          \
-  { 0x00000000, 0x00000000, 0x00000006 },      /* LINK_OR_CTR_REGS */  \
-  { 0x00000000, 0x00000000, 0x00000007 },      /* SPECIAL_REGS */      \
-  { 0xffffffff, 0x00000000, 0x0000000f },      /* SPEC_OR_GEN_REGS */  \
-  { 0x00000000, 0x00000000, 0x00000010 },      /* CR0_REGS */          \
-  { 0x00000000, 0x00000000, 0x00000ff0 },      /* CR_REGS */           \
-  { 0xffffffff, 0x00000000, 0x0000ffff },      /* NON_FLOAT_REGS */    \
-  { 0x00000000, 0x00000000, 0x00010000 },      /* XER_REGS */          \
-  { 0xffffffff, 0xffffffff, 0x0001ffff }       /* ALL_REGS */          \
+#define REG_CLASS_CONTENTS                                                  \
+{                                                                           \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */         \
+  { 0xfffffffe, 0x00000000, 0x00000008, 0x00000000 }, /* BASE_REGS */       \
+  { 0xffffffff, 0x00000000, 0x00000008, 0x00000000 }, /* GENERAL_REGS */     \
+  { 0x00000000, 0xffffffff, 0x00000000, 0x00000000 }, /* FLOAT_REGS */       \
+  { 0x00000000, 0x00000000, 0xffffe000, 0x0001ffff }, /* ALTIVEC_REGS */     \
+  { 0x00000000, 0x00000000, 0x00000000, 0x00020000 }, /* VRSAVE_REGS */             \
+  { 0xffffffff, 0xffffffff, 0x00000008, 0x00000000 }, /* NON_SPECIAL_REGS */ \
+  { 0x00000000, 0x00000000, 0x00000001, 0x00000000 }, /* MQ_REGS */         \
+  { 0x00000000, 0x00000000, 0x00000002, 0x00000000 }, /* LINK_REGS */       \
+  { 0x00000000, 0x00000000, 0x00000004, 0x00000000 }, /* CTR_REGS */        \
+  { 0x00000000, 0x00000000, 0x00000006, 0x00000000 }, /* LINK_OR_CTR_REGS */ \
+  { 0x00000000, 0x00000000, 0x00000007, 0x00000000 }, /* SPECIAL_REGS */     \
+  { 0xffffffff, 0x00000000, 0x0000000f, 0x00000000 }, /* SPEC_OR_GEN_REGS */ \
+  { 0x00000000, 0x00000000, 0x00000010, 0x00000000 }, /* CR0_REGS */        \
+  { 0x00000000, 0x00000000, 0x00000ff0, 0x00000000 }, /* CR_REGS */         \
+  { 0xffffffff, 0x00000000, 0x0000ffff, 0x00000000 }, /* NON_FLOAT_REGS */   \
+  { 0x00000000, 0x00000000, 0x00010000, 0x00000000 }, /* XER_REGS */        \
+  { 0xffffffff, 0xffffffff, 0xffffffff, 0x0001ffff }  /* ALL_REGS */        \
 }
 
 /* The same information, inverted:
@@ -984,6 +1078,7 @@ enum reg_class
  ((REGNO) == 0 ? GENERAL_REGS                  \
   : (REGNO) < 32 ? BASE_REGS                   \
   : FP_REGNO_P (REGNO) ? FLOAT_REGS            \
+  : ALTIVEC_REGNO_P (REGNO) ? ALTIVEC_REGS     \
   : (REGNO) == CR0_REGNO ? CR0_REGS            \
   : CR_REGNO_P (REGNO) ? CR_REGS               \
   : (REGNO) == MQ_REGNO ? MQ_REGS              \
@@ -991,6 +1086,7 @@ enum reg_class
   : (REGNO) == COUNT_REGISTER_REGNUM ? CTR_REGS        \
   : (REGNO) == ARG_POINTER_REGNUM ? BASE_REGS  \
   : (REGNO) == XER_REGNO ? XER_REGS            \
+  : (REGNO) == VRSAVE_REGNO ? VRSAVE_REGS      \
   : NO_REGS)
 
 /* The class value for index registers, and the one for base regs.  */
@@ -1006,6 +1102,7 @@ enum reg_class
    : (C) == 'q' ? MQ_REGS      \
    : (C) == 'c' ? CTR_REGS     \
    : (C) == 'l' ? LINK_REGS    \
+   : (C) == 'v' ? ALTIVEC_REGS \
    : (C) == 'x' ? CR0_REGS     \
    : (C) == 'y' ? CR_REGS      \
    : (C) == 'z' ? XER_REGS     \
@@ -1103,11 +1200,14 @@ enum reg_class
 #define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
   secondary_reload_class (CLASS, MODE, IN)
 
-/* If we are copying between FP registers and anything else, we need a memory
-   location.  */
+/* If we are copying between FP or AltiVec registers and anything
+   else, we need a memory location.  */
 
-#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
- ((CLASS1) != (CLASS2) && ((CLASS1) == FLOAT_REGS || (CLASS2) == FLOAT_REGS))
+#define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE)            \
+ ((CLASS1) != (CLASS2) && ((CLASS1) == FLOAT_REGS              \
+                          || (CLASS2) == FLOAT_REGS            \
+                          || (CLASS1) == ALTIVEC_REGS          \
+                          || (CLASS2) == ALTIVEC_REGS))
 
 /* Return the maximum number of consecutive registers
    needed to represent mode MODE in a register of class CLASS.
@@ -1294,16 +1394,18 @@ typedef struct rs6000_stack {
                && TYPE_PRECISION (VALTYPE) < BITS_PER_WORD)    \
               || POINTER_TYPE_P (VALTYPE)                      \
               ? word_mode : TYPE_MODE (VALTYPE),               \
-              TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_HARD_FLOAT \
+              TREE_CODE (VALTYPE) == VECTOR_TYPE ? ALTIVEC_ARG_RETURN \
+              : TREE_CODE (VALTYPE) == REAL_TYPE && TARGET_HARD_FLOAT \
                ? FP_ARG_RETURN : GP_ARG_RETURN)
 
 /* Define how to find the value returned by a library function
    assuming the value has mode MODE.  */
 
-#define LIBCALL_VALUE(MODE)                                    \
-  gen_rtx_REG (MODE, (GET_MODE_CLASS (MODE) == MODE_FLOAT      \
-                     && TARGET_HARD_FLOAT                      \
-                     ? FP_ARG_RETURN : GP_ARG_RETURN))
+#define LIBCALL_VALUE(MODE)                                            \
+  gen_rtx_REG (MODE, ALTIVEC_VECTOR_MODE (MODE) ? ALTIVEC_ARG_RETURN   \
+                    : GET_MODE_CLASS (MODE) == MODE_FLOAT              \
+                    && TARGET_HARD_FLOAT                               \
+                    ? FP_ARG_RETURN : GP_ARG_RETURN)
 
 /* The definition of this macro implies that there are cases where
    a scalar value cannot be returned in registers.
@@ -1338,9 +1440,15 @@ typedef struct rs6000_stack {
                        ? FP_ARG_AIX_MAX_REG : FP_ARG_V4_MAX_REG)
 #define FP_ARG_NUM_REG (FP_ARG_MAX_REG - FP_ARG_MIN_REG + 1)
 
+/* Minimum and maximum AltiVec registers used to hold arguments.  */
+#define ALTIVEC_ARG_MIN_REG (FIRST_ALTIVEC_REGNO + 2)
+#define ALTIVEC_ARG_MAX_REG (ALTIVEC_ARG_MIN_REG + 11)
+#define ALTIVEC_ARG_NUM_REG (ALTIVEC_ARG_MAX_REG - ALTIVEC_ARG_MIN_REG + 1)
+
 /* Return registers */
 #define GP_ARG_RETURN GP_ARG_MIN_REG
 #define FP_ARG_RETURN FP_ARG_MIN_REG
+#define ALTIVEC_ARG_RETURN (FIRST_ALTIVEC_REGNO + 2)
 
 /* Flags for the call/call_value rtl operations set up by function_arg */
 #define CALL_NORMAL            0x00000000      /* no special processing */
@@ -1352,13 +1460,19 @@ typedef struct rs6000_stack {
 /* 1 if N is a possible register number for a function value
    as seen by the caller.
 
-   On RS/6000, this is r3 and fp1.  */
-#define FUNCTION_VALUE_REGNO_P(N)  ((N) == GP_ARG_RETURN || ((N) == FP_ARG_RETURN))
+   On RS/6000, this is r3, fp1, and v2 (for AltiVec).  */
+#define FUNCTION_VALUE_REGNO_P(N)  ((N) == GP_ARG_RETURN       \
+                                   || ((N) == FP_ARG_RETURN)   \
+                                   || (TARGET_ALTIVEC &&       \
+                                       (N) == ALTIVEC_ARG_RETURN))
 
 /* 1 if N is a possible register number for function argument passing.
-   On RS/6000, these are r3-r10 and fp1-fp13.  */
+   On RS/6000, these are r3-r10 and fp1-fp13.
+   On AltiVec, v2 - v13 are used for passing vectors.  */
 #define FUNCTION_ARG_REGNO_P(N)                                                \
   ((unsigned)(((N) - GP_ARG_MIN_REG) < (unsigned)(GP_ARG_NUM_REG))     \
+   || (TARGET_ALTIVEC &&                                               \
+       (unsigned)((N) - ALTIVEC_ARG_MIN_REG) < (unsigned)(ALTIVEC_ARG_MAX_REG)) \
    || ((unsigned)((N) - FP_ARG_MIN_REG) < (unsigned)(FP_ARG_NUM_REG)))
 
 \f
@@ -1394,6 +1508,7 @@ typedef struct rs6000_args
 {
   int words;                   /* # words used for passing GP registers */
   int fregno;                  /* next available FP register */
+  int vregno;                  /* next available AltiVec register */
   int nargs_prototype;         /* # args left in the current prototype */
   int orig_nargs;              /* Original value of nargs_prototype */
   int prototype;               /* Whether a prototype was defined */
@@ -1436,6 +1551,12 @@ typedef struct rs6000_args
    && (CUM).fregno <= FP_ARG_MAX_REG    \
    && TARGET_HARD_FLOAT)
 
+/* Non-zero if we can use an AltiVec register to pass this arg.  */
+#define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE)   \
+  (ALTIVEC_VECTOR_MODE (MODE)                  \
+   && (CUM).vregno <= ALTIVEC_ARG_MAX_REG      \
+   && TARGET_ALTIVEC_ABI)
+
 /* Determine where to put an argument to a function.
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
@@ -1778,6 +1899,7 @@ typedef struct rs6000_args
   && GET_CODE (XEXP (X, 0)) == REG                             \
   && INT_REG_OK_FOR_BASE_P (XEXP (X, 0), (STRICT))             \
   && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 0)             \
+  && (! ALTIVEC_VECTOR_MODE (MODE) || INTVAL (X) == 0)         \
   && (((MODE) != DFmode && (MODE) != DImode)                   \
       || (TARGET_32BIT                                         \
          ? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 4)       \
@@ -1805,6 +1927,7 @@ typedef struct rs6000_args
    && ! flag_pic && ! TARGET_TOC                               \
    && (MODE) != DImode                                         \
    && (MODE) != TImode                                         \
+   && ! ALTIVEC_VECTOR_MODE (MODE)                             \
    && (TARGET_HARD_FLOAT || (MODE) != DFmode)                  \
    && GET_CODE (X) == LO_SUM                                   \
    && GET_CODE (XEXP (X, 0)) == REG                            \
@@ -2389,6 +2512,40 @@ extern char rs6000_reg_names[][8];       /* register names (0 vs. %r0). */
   &rs6000_reg_names[75][0],    /* cr7  */                              \
                                                                        \
   &rs6000_reg_names[76][0],    /* xer  */                              \
+                                                                       \
+  &rs6000_reg_names[77][0],    /* v0  */                               \
+  &rs6000_reg_names[78][0],    /* v1  */                               \
+  &rs6000_reg_names[79][0],    /* v2  */                               \
+  &rs6000_reg_names[80][0],    /* v3  */                               \
+  &rs6000_reg_names[81][0],    /* v4  */                               \
+  &rs6000_reg_names[82][0],    /* v5  */                               \
+  &rs6000_reg_names[83][0],    /* v6  */                               \
+  &rs6000_reg_names[84][0],    /* v7  */                               \
+  &rs6000_reg_names[85][0],    /* v8  */                               \
+  &rs6000_reg_names[86][0],    /* v9  */                               \
+  &rs6000_reg_names[87][0],    /* v10  */                              \
+  &rs6000_reg_names[88][0],    /* v11  */                              \
+  &rs6000_reg_names[89][0],    /* v12  */                              \
+  &rs6000_reg_names[90][0],    /* v13  */                              \
+  &rs6000_reg_names[91][0],    /* v14  */                              \
+  &rs6000_reg_names[92][0],    /* v15  */                              \
+  &rs6000_reg_names[93][0],    /* v16  */                              \
+  &rs6000_reg_names[94][0],    /* v17  */                              \
+  &rs6000_reg_names[95][0],    /* v18  */                              \
+  &rs6000_reg_names[96][0],    /* v19  */                              \
+  &rs6000_reg_names[97][0],    /* v20  */                              \
+  &rs6000_reg_names[98][0],    /* v21  */                              \
+  &rs6000_reg_names[99][0],    /* v22  */                              \
+  &rs6000_reg_names[100][0],   /* v23  */                              \
+  &rs6000_reg_names[101][0],   /* v24  */                              \
+  &rs6000_reg_names[102][0],   /* v25  */                              \
+  &rs6000_reg_names[103][0],   /* v26  */                              \
+  &rs6000_reg_names[104][0],   /* v27  */                              \
+  &rs6000_reg_names[105][0],   /* v28  */                              \
+  &rs6000_reg_names[106][0],   /* v29  */                              \
+  &rs6000_reg_names[107][0],   /* v30  */                              \
+  &rs6000_reg_names[108][0],   /* v31  */                              \
+  &rs6000_reg_names[109][0],   /* vrsave  */                           \
 }
 
 /* print-rtl can't handle the above REGISTER_NAMES, so define the
@@ -2407,7 +2564,12 @@ extern char rs6000_reg_names[][8];       /* register names (0 vs. %r0). */
     "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",            \
      "mq",  "lr", "ctr",  "ap",                                                \
     "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",            \
-  "xer"                                                                        \
+  "xer",                                                               \
+     "v0",  "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",             \
+     "v8",  "v9", "v10", "v11", "v12", "v13", "v14", "v15",             \
+    "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",             \
+    "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",             \
+    "vrsave"                                                           \
 }
 
 /* Table of additional register names to use in user input.  */
@@ -2429,6 +2591,15 @@ extern char rs6000_reg_names[][8];       /* register names (0 vs. %r0). */
   {"fr20", 52}, {"fr21", 53}, {"fr22", 54}, {"fr23", 55},      \
   {"fr24", 56}, {"fr25", 57}, {"fr26", 58}, {"fr27", 59},      \
   {"fr28", 60}, {"fr29", 61}, {"fr30", 62}, {"fr31", 63},      \
+  {"v0",   77}, {"v1",   78}, {"v2",   79}, {"v3",   80},       \
+  {"v4",   81}, {"v5",   82}, {"v6",   83}, {"v7",   84},       \
+  {"v8",   85}, {"v9",   86}, {"v10",  87}, {"v11",  88},       \
+  {"v12",  89}, {"v13",  90}, {"v14",  91}, {"v15",  92},       \
+  {"v16",  93}, {"v17",  94}, {"v18",  95}, {"v19",  96},       \
+  {"v20",  97}, {"v21",  98}, {"v22",  99}, {"v23",  100},     \
+  {"v24",  101},{"v25",  102},{"v26",  103},{"v27",  104},      \
+  {"v28",  105},{"v29",  106},{"v30",  107},{"v31",  108},      \
+  {"vrsave", 109},                                             \
   /* no additional names for: mq, lr, ctr, ap */               \
   {"cr0",  68}, {"cr1",  69}, {"cr2",  70}, {"cr3",  71},      \
   {"cr4",  72}, {"cr5",  73}, {"cr6",  74}, {"cr7",  75},      \
@@ -2629,3 +2800,116 @@ extern int flag_pic;
 extern int optimize;
 extern int flag_expensive_optimizations;
 extern int frame_pointer_needed;
+
+enum rs6000_builtins
+{
+  /* AltiVec builtins.  */
+  ALTIVEC_BUILTIN_ST_INTERNAL,
+  ALTIVEC_BUILTIN_LD_INTERNAL,
+  ALTIVEC_BUILTIN_VADDUBM,
+  ALTIVEC_BUILTIN_VADDUHM,
+  ALTIVEC_BUILTIN_VADDUWM,
+  ALTIVEC_BUILTIN_VADDFP,
+  ALTIVEC_BUILTIN_VADDCUW,
+  ALTIVEC_BUILTIN_VADDUBS,
+  ALTIVEC_BUILTIN_VADDSBS,
+  ALTIVEC_BUILTIN_VADDUHS,
+  ALTIVEC_BUILTIN_VADDSHS,
+  ALTIVEC_BUILTIN_VADDUWS,
+  ALTIVEC_BUILTIN_VADDSWS,
+  ALTIVEC_BUILTIN_VAND,
+  ALTIVEC_BUILTIN_VANDC,
+  ALTIVEC_BUILTIN_VAVGUB,
+  ALTIVEC_BUILTIN_VAVGSB,
+  ALTIVEC_BUILTIN_VAVGUH,
+  ALTIVEC_BUILTIN_VAVGSH,
+  ALTIVEC_BUILTIN_VAVGUW,
+  ALTIVEC_BUILTIN_VAVGSW,
+  ALTIVEC_BUILTIN_VCMPBFP,
+  ALTIVEC_BUILTIN_VCMPEQUB,
+  ALTIVEC_BUILTIN_VCMPEQUH,
+  ALTIVEC_BUILTIN_VCMPEQUW,
+  ALTIVEC_BUILTIN_VCMPEQFP,
+  ALTIVEC_BUILTIN_VCMPGEFP,
+  ALTIVEC_BUILTIN_VCMPGTUB,
+  ALTIVEC_BUILTIN_VCMPGTSB,
+  ALTIVEC_BUILTIN_VCMPGTUH,
+  ALTIVEC_BUILTIN_VCMPGTSH,
+  ALTIVEC_BUILTIN_VCMPGTUW,
+  ALTIVEC_BUILTIN_VCMPGTSW,
+  ALTIVEC_BUILTIN_VCMPGTFP,
+  ALTIVEC_BUILTIN_VMAXUB,
+  ALTIVEC_BUILTIN_VMAXSB,
+  ALTIVEC_BUILTIN_VMAXUH,
+  ALTIVEC_BUILTIN_VMAXSH,
+  ALTIVEC_BUILTIN_VMAXUW,
+  ALTIVEC_BUILTIN_VMAXSW,
+  ALTIVEC_BUILTIN_VMAXFP,
+  ALTIVEC_BUILTIN_VMRGHB,
+  ALTIVEC_BUILTIN_VMRGHH,
+  ALTIVEC_BUILTIN_VMRGHW,
+  ALTIVEC_BUILTIN_VMRGLB,
+  ALTIVEC_BUILTIN_VMRGLH,
+  ALTIVEC_BUILTIN_VMRGLW,
+  ALTIVEC_BUILTIN_VMINUB,
+  ALTIVEC_BUILTIN_VMINSB,
+  ALTIVEC_BUILTIN_VMINUH,
+  ALTIVEC_BUILTIN_VMINSH,
+  ALTIVEC_BUILTIN_VMINUW,
+  ALTIVEC_BUILTIN_VMINSW,
+  ALTIVEC_BUILTIN_VMINFP,
+  ALTIVEC_BUILTIN_VMULEUB,
+  ALTIVEC_BUILTIN_VMULESB,
+  ALTIVEC_BUILTIN_VMULEUH,
+  ALTIVEC_BUILTIN_VMULESH,
+  ALTIVEC_BUILTIN_VMULOUB,
+  ALTIVEC_BUILTIN_VMULOSB,
+  ALTIVEC_BUILTIN_VMULOUH,
+  ALTIVEC_BUILTIN_VMULOSH,
+  ALTIVEC_BUILTIN_VNOR,
+  ALTIVEC_BUILTIN_VOR,
+  ALTIVEC_BUILTIN_VPKUHUM,
+  ALTIVEC_BUILTIN_VPKUWUM,
+  ALTIVEC_BUILTIN_VPKPX,
+  ALTIVEC_BUILTIN_VPKUHSS,
+  ALTIVEC_BUILTIN_VPKSHSS,
+  ALTIVEC_BUILTIN_VPKUWSS,
+  ALTIVEC_BUILTIN_VPKSWSS,
+  ALTIVEC_BUILTIN_VPKUHUS,
+  ALTIVEC_BUILTIN_VPKSHUS,
+  ALTIVEC_BUILTIN_VPKUWUS,
+  ALTIVEC_BUILTIN_VPKSWUS,
+  ALTIVEC_BUILTIN_VRLB,
+  ALTIVEC_BUILTIN_VRLH,
+  ALTIVEC_BUILTIN_VRLW,
+  ALTIVEC_BUILTIN_VSLB,
+  ALTIVEC_BUILTIN_VSLH,
+  ALTIVEC_BUILTIN_VSLW,
+  ALTIVEC_BUILTIN_VSL,
+  ALTIVEC_BUILTIN_VSLO,
+  ALTIVEC_BUILTIN_VSRB,
+  ALTIVEC_BUILTIN_VRSH,
+  ALTIVEC_BUILTIN_VRSW,
+  ALTIVEC_BUILTIN_VSRAB,
+  ALTIVEC_BUILTIN_VSRAH,
+  ALTIVEC_BUILTIN_VSRAW,
+  ALTIVEC_BUILTIN_VSR,
+  ALTIVEC_BUILTIN_VSRO,
+  ALTIVEC_BUILTIN_VSUBUBM,
+  ALTIVEC_BUILTIN_VSUBUHM,
+  ALTIVEC_BUILTIN_VSUBUWM,
+  ALTIVEC_BUILTIN_VSUBFP,
+  ALTIVEC_BUILTIN_VSUBCUW,
+  ALTIVEC_BUILTIN_VSUBUBS,
+  ALTIVEC_BUILTIN_VSUBSBS,
+  ALTIVEC_BUILTIN_VSUBUHS,
+  ALTIVEC_BUILTIN_VSUBSHS,
+  ALTIVEC_BUILTIN_VSUBUWS,
+  ALTIVEC_BUILTIN_VSUBSWS,
+  ALTIVEC_BUILTIN_VSUM4UBS,
+  ALTIVEC_BUILTIN_VSUM4SBS,
+  ALTIVEC_BUILTIN_VSUM4SHS,
+  ALTIVEC_BUILTIN_VSUM2SWS,
+  ALTIVEC_BUILTIN_VSUMSWS,
+  ALTIVEC_BUILTIN_VXOR
+};
index 3d13a82fa7c8cc39146e4ba4c5b74ba8c0372045..5c3191a211768451f1374caa97fe86efbb5128f9 100644 (file)
@@ -37,7 +37,7 @@
 \f
 ;; Define an insn type attribute.  This is used in function unit delay
 ;; computations.
-(define_attr "type" "integer,load,store,fpload,fpstore,imul,lmul,idiv,ldiv,branch,compare,cr_logical,delayed_compare,fpcompare,mtjmpr,fp,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg"
+(define_attr "type" "integer,load,store,fpload,fpstore,imul,lmul,idiv,ldiv,branch,compare,cr_logical,delayed_compare,fpcompare,mtjmpr,fp,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,altivec"
   (const_string "integer"))
 
 ;; Length (in bytes).
     emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), operands[0]);
   DONE;
 }")
+
+;; AltiVec patterns
+
+;; Generic LVX load instruction.
+(define_insn "altivec_lvx"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+       (match_operand:V4SI 1 "memory_operand" "m"))]
+  "TARGET_ALTIVEC"
+  "lvx\t%0,%y1"
+  [(set_attr "type" "altivec")])
+
+;; Generic STVX store instruction.
+(define_insn "altivec_stvx"
+  [(set (match_operand:V4SI 0 "memory_operand" "=m")
+       (match_operand:V4SI 1 "register_operand" "v"))]
+  "TARGET_ALTIVEC"
+  "stvx\t%1,%y0"
+  [(set_attr "type" "altivec")])
+
+;; Vector move instructions.
+(define_expand "movv4si"
+  [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
+       (match_operand:V4SI 1 "any_operand" ""))]
+  "TARGET_ALTIVEC"
+  "{ rs6000_emit_move (operands[0], operands[1], V4SImode); DONE; }")
+
+(define_insn "*movv4si_internal"
+  [(set (match_operand:V4SI 0 "nonimmediate_operand" "=m,v,v")
+       (match_operand:V4SI 1 "input_operand" "v,m,v"))]
+  "TARGET_ALTIVEC"
+  "@
+   stvx\t%1,%y0
+   ldvx\t%0,%y1
+   vor\t%0,%1,%1"
+  [(set_attr "type" "altivec")])
+
+(define_expand "movv8hi"
+  [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
+       (match_operand:V8HI 1 "any_operand" ""))]
+  "TARGET_ALTIVEC"
+  "{ rs6000_emit_move (operands[0], operands[1], V8HImode); DONE; }")
+
+(define_insn "*movv8hi_internal1"
+  [(set (match_operand:V8HI 0 "nonimmediate_operand" "=m,v,v")
+       (match_operand:V8HI 1 "input_operand" "v,m,v"))]
+  "TARGET_ALTIVEC"
+  "@
+   stvx\t%1,%y0
+   ldvx\t%0,%y1
+   vor\t%0,%1,%1"
+  [(set_attr "type" "altivec")])
+
+(define_expand "movv16qi"
+  [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
+       (match_operand:V16QI 1 "any_operand" ""))]
+  "TARGET_ALTIVEC"
+  "{ rs6000_emit_move (operands[0], operands[1], V16QImode); DONE; }")
+
+(define_insn "*movv16qi_internal1"
+  [(set (match_operand:V16QI 0 "nonimmediate_operand" "=m,v,v")
+       (match_operand:V16QI 1 "input_operand" "v,m,v"))]
+  "TARGET_ALTIVEC"
+  "@
+   stvx\t%1,%y0
+   ldvx\t%0,%y1
+   vor\t%0,%1,%1"
+  [(set_attr "type" "altivec")])
+
+(define_expand "movv4sf"
+  [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
+       (match_operand:V4SF 1 "any_operand" ""))]
+  "TARGET_ALTIVEC"
+  "{ rs6000_emit_move (operands[0], operands[1], V4SFmode); DONE; }")
+
+(define_insn "*movv4sf_internal1"
+  [(set (match_operand:V4SF 0 "nonimmediate_operand" "=m,v,v")
+       (match_operand:V4SF 1 "input_operand" "v,m,v"))]
+  "TARGET_ALTIVEC"
+  "@
+   stvx\t%1,%y0
+   ldvx\t%0,%y1
+   vor\t%0,%1,%1"
+  [(set_attr "type" "altivec")])
+
+;; Simple binary operations.
+
+(define_insn "altivec_vaddubm"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 31))]
+  "TARGET_ALTIVEC"
+  "vaddubm\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vadduhm"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 32))]
+  "TARGET_ALTIVEC"
+  "vadduhm\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vadduwm"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 33))]
+  "TARGET_ALTIVEC"
+  "vadduwm\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vaddfp"
+  [(set (match_operand:V4SF 0 "register_operand" "=v")
+        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
+                      (match_operand:V4SF 2 "register_operand" "v")] 34))]
+  "TARGET_ALTIVEC"
+  "vaddfp\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vaddcuw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 35))]
+  "TARGET_ALTIVEC"
+  "vaddcuw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vaddubs"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 36))]
+  "TARGET_ALTIVEC"
+  "vaddubs\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vaddsbs"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 37))]
+  "TARGET_ALTIVEC"
+  "vaddsbs\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vadduhs"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 38))]
+  "TARGET_ALTIVEC"
+  "vadduhs\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vaddshs"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 39))]
+  "TARGET_ALTIVEC"
+  "vaddshs\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vadduws"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 40))]
+  "TARGET_ALTIVEC"
+  "vadduws\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vaddsws"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 41))]
+  "TARGET_ALTIVEC"
+  "vaddsws\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vand"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 42))]
+  "TARGET_ALTIVEC"
+  "vand\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vandc"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 43))]
+  "TARGET_ALTIVEC"
+  "vandc\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vavgub"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 44))]
+  "TARGET_ALTIVEC"
+  "vavgub\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vavgsb"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 45))]
+  "TARGET_ALTIVEC"
+  "vavgsb\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vavguh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 46))]
+  "TARGET_ALTIVEC"
+  "vavguh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vavgsh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 47))]
+  "TARGET_ALTIVEC"
+  "vavgsh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vavguw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 48))]
+  "TARGET_ALTIVEC"
+  "vavguw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vavgsw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 49))]
+  "TARGET_ALTIVEC"
+  "vavgsw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vcmpbfp"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+                      (match_operand:V4SF 2 "register_operand" "v")] 50))]
+  "TARGET_ALTIVEC"
+  "vcmpbfp\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vcmpequb"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 51))]
+  "TARGET_ALTIVEC"
+  "vcmpequb\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vcmpequh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 52))]
+  "TARGET_ALTIVEC"
+  "vcmpequh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vcmpequw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 53))]
+  "TARGET_ALTIVEC"
+  "vcmpequw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vcmpeqfp"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+                      (match_operand:V4SF 2 "register_operand" "v")] 54))]
+  "TARGET_ALTIVEC"
+  "vcmpeqfp\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vcmpgefp"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+                      (match_operand:V4SF 2 "register_operand" "v")] 55))]
+  "TARGET_ALTIVEC"
+  "vcmpgefp\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vcmpgtub"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 56))]
+  "TARGET_ALTIVEC"
+  "vcmpgtub\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vcmpgtsb"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 57))]
+  "TARGET_ALTIVEC"
+  "vcmpgtsb\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vcmpgtuh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 58))]
+  "TARGET_ALTIVEC"
+  "vcmpgtuh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vcmpgtsh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 59))]
+  "TARGET_ALTIVEC"
+  "vcmpgtsh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vcmpgtuw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 60))]
+  "TARGET_ALTIVEC"
+  "vcmpgtuw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vcmpgtsw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 61))]
+  "TARGET_ALTIVEC"
+  "vcmpgtsw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vcmpgtfp"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
+                      (match_operand:V4SF 2 "register_operand" "v")] 62))]
+  "TARGET_ALTIVEC"
+  "vcmpgtfp\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmaxub"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 63))]
+  "TARGET_ALTIVEC"
+  "vmaxub\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmaxsb"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 64))]
+  "TARGET_ALTIVEC"
+  "vmaxsb\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmaxuh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 65))]
+  "TARGET_ALTIVEC"
+  "vmaxuh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmaxsh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 66))]
+  "TARGET_ALTIVEC"
+  "vmaxsh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmaxuw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 67))]
+  "TARGET_ALTIVEC"
+  "vmaxuw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmaxsw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 68))]
+  "TARGET_ALTIVEC"
+  "vmaxsw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmaxfp"
+  [(set (match_operand:V4SF 0 "register_operand" "=v")
+        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
+                      (match_operand:V4SF 2 "register_operand" "v")] 69))]
+  "TARGET_ALTIVEC"
+  "vmaxfp\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmrghb"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 70))]
+  "TARGET_ALTIVEC"
+  "vmrghb\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmrghh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 71))]
+  "TARGET_ALTIVEC"
+  "vmrghh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmrghw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 72))]
+  "TARGET_ALTIVEC"
+  "vmrghw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmrglb"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 73))]
+  "TARGET_ALTIVEC"
+  "vmrglb\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmrglh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 74))]
+  "TARGET_ALTIVEC"
+  "vmrglh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmrglw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 75))]
+  "TARGET_ALTIVEC"
+  "vmrglw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vminub"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 76))]
+  "TARGET_ALTIVEC"
+  "vminub\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vminsb"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 77))]
+  "TARGET_ALTIVEC"
+  "vminsb\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vminuh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 78))]
+  "TARGET_ALTIVEC"
+  "vminuh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vminsh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 79))]
+  "TARGET_ALTIVEC"
+  "vminsh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vminuw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 80))]
+  "TARGET_ALTIVEC"
+  "vminuw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vminsw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 81))]
+  "TARGET_ALTIVEC"
+  "vminsw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vminfp"
+  [(set (match_operand:V4SF 0 "register_operand" "=v")
+        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
+                      (match_operand:V4SF 2 "register_operand" "v")] 82))]
+  "TARGET_ALTIVEC"
+  "vminfp\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmuleub"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
+                      (match_operand:V16QI 2 "register_operand" "v")] 83))]
+  "TARGET_ALTIVEC"
+  "vmuleub\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmulesb"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
+                      (match_operand:V16QI 2 "register_operand" "v")] 84))]
+  "TARGET_ALTIVEC"
+  "vmulesb\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmuleuh"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 85))]
+  "TARGET_ALTIVEC"
+  "vmuleuh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmulesh"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 86))]
+  "TARGET_ALTIVEC"
+  "vmulesh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmuloub"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
+                      (match_operand:V16QI 2 "register_operand" "v")] 87))]
+  "TARGET_ALTIVEC"
+  "vmuloub\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmulosb"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
+                      (match_operand:V16QI 2 "register_operand" "v")] 88))]
+  "TARGET_ALTIVEC"
+  "vmulosb\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmulouh"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 89))]
+  "TARGET_ALTIVEC"
+  "vmulouh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vmulosh"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 90))]
+  "TARGET_ALTIVEC"
+  "vmulosh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vnor"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 91))]
+  "TARGET_ALTIVEC"
+  "vnor\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vor"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 92))]
+  "TARGET_ALTIVEC"
+  "vor\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vpkuhum"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
+                       (match_operand:V8HI 2 "register_operand" "v")] 93))]
+  "TARGET_ALTIVEC"
+  "vpkuhum\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vpkuwum"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 94))]
+  "TARGET_ALTIVEC"
+  "vpkuwum\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vpkpx"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 95))]
+  "TARGET_ALTIVEC"
+  "vpkpx\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vpkuhss"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
+                       (match_operand:V8HI 2 "register_operand" "v")] 96))]
+  "TARGET_ALTIVEC"
+  "vpkuhss\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vpkshss"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
+                       (match_operand:V8HI 2 "register_operand" "v")] 97))]
+  "TARGET_ALTIVEC"
+  "vpkshss\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vpkuwss"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 98))]
+  "TARGET_ALTIVEC"
+  "vpkuwss\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vpkswss"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 99))]
+  "TARGET_ALTIVEC"
+  "vpkswss\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vpkuhus"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
+                       (match_operand:V8HI 2 "register_operand" "v")] 100))]
+  "TARGET_ALTIVEC"
+  "vpkuhus\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vpkshus"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
+                       (match_operand:V8HI 2 "register_operand" "v")] 101))]
+  "TARGET_ALTIVEC"
+  "vpkshus\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vpkuwus"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 102))]
+  "TARGET_ALTIVEC"
+  "vpkuwus\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vpkswus"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 103))]
+  "TARGET_ALTIVEC"
+  "vpkswus\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vrlb"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 104))]
+  "TARGET_ALTIVEC"
+  "vrlb\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vrlh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 105))]
+  "TARGET_ALTIVEC"
+  "vrlh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vrlw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 106))]
+  "TARGET_ALTIVEC"
+  "vrlw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vslb"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 107))]
+  "TARGET_ALTIVEC"
+  "vslb\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vslh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 108))]
+  "TARGET_ALTIVEC"
+  "vslh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vslw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 109))]
+  "TARGET_ALTIVEC"
+  "vslw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsl"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 110))]
+  "TARGET_ALTIVEC"
+  "vsl\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vslo"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 111))]
+  "TARGET_ALTIVEC"
+  "vslo\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsrb"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 112))]
+  "TARGET_ALTIVEC"
+  "vsrb\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vrsh"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 113))]
+  "TARGET_ALTIVEC"
+  "vrsh\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vrsw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 114))]
+  "TARGET_ALTIVEC"
+  "vrsw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsrab"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 115))]
+  "TARGET_ALTIVEC"
+  "vsrab\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsrah"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 116))]
+  "TARGET_ALTIVEC"
+  "vsrah\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsraw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 117))]
+  "TARGET_ALTIVEC"
+  "vsraw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsr"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 118))]
+  "TARGET_ALTIVEC"
+  "vsr\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsro"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 119))]
+  "TARGET_ALTIVEC"
+  "vsro\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsububm"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 120))]
+  "TARGET_ALTIVEC"
+  "vsububm\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsubuhm"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 121))]
+  "TARGET_ALTIVEC"
+  "vsubuhm\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsubuwm"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 122))]
+  "TARGET_ALTIVEC"
+  "vsubuwm\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsubfp"
+  [(set (match_operand:V4SF 0 "register_operand" "=v")
+        (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
+                      (match_operand:V4SF 2 "register_operand" "v")] 123))]
+  "TARGET_ALTIVEC"
+  "vsubfp\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsubcuw"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 124))]
+  "TARGET_ALTIVEC"
+  "vsubcuw\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsububs"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 125))]
+  "TARGET_ALTIVEC"
+  "vsububs\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsubsbs"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+        (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                       (match_operand:V16QI 2 "register_operand" "v")] 126))]
+  "TARGET_ALTIVEC"
+  "vsubsbs\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsubuhs"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 127))]
+  "TARGET_ALTIVEC"
+  "vsubuhs\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsubshs"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+        (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V8HI 2 "register_operand" "v")] 128))]
+  "TARGET_ALTIVEC"
+  "vsubshs\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsubuws"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 129))]
+  "TARGET_ALTIVEC"
+  "vsubuws\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsubsws"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 130))]
+  "TARGET_ALTIVEC"
+  "vsubsws\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsum4ubs"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 131))]
+  "TARGET_ALTIVEC"
+  "vsum4ubs\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsum4sbs"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 132))]
+  "TARGET_ALTIVEC"
+  "vsum4sbs\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsum4shs"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 133))]
+  "TARGET_ALTIVEC"
+  "vsum4shs\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsum2sws"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 134))]
+  "TARGET_ALTIVEC"
+  "vsum2sws\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vsumsws"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 135))]
+  "TARGET_ALTIVEC"
+  "vsumsws\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
+
+(define_insn "altivec_vxor"
+  [(set (match_operand:V4SI 0 "register_operand" "=v")
+        (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                      (match_operand:V4SI 2 "register_operand" "v")] 136))]
+  "TARGET_ALTIVEC"
+  "vxor\t%0,%1,%2"
+  [(set_attr "type" "altivec")])
index a6f79a1dc501ed9ef8dc9825f22db33c28d897fd..fcff961c90dbaa672958375d0a1952b0f7464658 100644 (file)
@@ -400,18 +400,31 @@ do {                                                                      \
    one set of libraries with -mno-eabi instead of eabi libraries and non-eabi
    versions, just use 64 as the stack boundary.  */
 #undef STACK_BOUNDARY
-#define        STACK_BOUNDARY  64
+#define        STACK_BOUNDARY  (TARGET_ALTIVEC_ABI ? 128 : 64)
 
 /* Real stack boundary as mandated by the appropriate ABI.  */
-#define ABI_STACK_BOUNDARY ((TARGET_EABI) ? 64 : 128)
+#define ABI_STACK_BOUNDARY ((TARGET_EABI && !TARGET_ALTIVEC_ABI) ? 64 : 128)
 
 /* No data type wants to be aligned rounder than this.  */
 #undef BIGGEST_ALIGNMENT
-#define BIGGEST_ALIGNMENT ((TARGET_EABI) ? 64 : 128)
+#define BIGGEST_ALIGNMENT (TARGET_EABI ? 64 : 128)
+
+/* An expression for the alignment of a structure field FIELD if the
+   alignment computed in the usual way is COMPUTED.  */
+#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED)                                  \
+       ((TARGET_ALTIVEC && TREE_CODE (TREE_TYPE (FIELD)) == VECTOR_TYPE)     \
+        ? 128 : COMPUTED)
+
+/* Define this macro as an expression for the alignment of a type
+   (given by TYPE as a tree node) if the alignment computed in the
+   usual way is COMPUTED and the alignment explicitly specified was
+   SPECIFIED.  */
+#define ROUND_TYPE_ALIGN(TYPE, COMPUTED, SPECIFIED)                    \
+       ((TARGET_ALTIVEC  && TREE_CODE (TYPE) == VECTOR_TYPE)           \
+        ? 128 : MAX (COMPUTED, SPECIFIED))
 
 #undef  BIGGEST_FIELD_ALIGNMENT
 #undef  ADJUST_FIELD_ALIGN
-#undef  ROUND_TYPE_ALIGN
 
 /* Use ELF style section commands.  */
 
index b5e864e61dc49cfa94332b92cf469335c70c45da..9ad11f4232c170fe46aa032262719ffebf6fa504 100644 (file)
@@ -424,6 +424,7 @@ in the following sections.
 -mtune=@var{cpu-type} @gol
 -mpower  -mno-power  -mpower2  -mno-power2 @gol
 -mpowerpc  -mpowerpc64  -mno-powerpc @gol
+-maltivec -mno-altivec @gol
 -mpowerpc-gpopt  -mno-powerpc-gpopt @gol
 -mpowerpc-gfxopt  -mno-powerpc-gfxopt @gol
 -mnew-mnemonics  -mold-mnemonics @gol
@@ -436,6 +437,7 @@ in the following sections.
 -mno-relocatable  -mrelocatable-lib  -mno-relocatable-lib @gol
 -mtoc  -mno-toc -mlittle  -mlittle-endian  -mbig  -mbig-endian @gol
 -mcall-aix -mcall-sysv -mcall-netbsd @gol
+-mabi=altivec @gol
 -mprototype  -mno-prototype @gol
 -msim  -mmvme  -mads  -myellowknife  -memb -msdata @gol
 -msdata=@var{opt}  -mvxworks -G @var{num}}
@@ -6684,6 +6686,15 @@ values for @var{cpu_type} are used for @option{-mtune} as for
 architecture, registers, and mnemonics set by @option{-mcpu}, but the
 scheduling parameters set by @option{-mtune}.
 
+@item -maltivec
+@itemx -mno-altivec
+@opindex maltivec
+@opindex mno-altivec
+These switches enable or disable the use of built-in functions that
+allow access to the AltiVec instruction set.  You may also need to set
+@option{-mabi=altivec} to adjust the current ABI with AltiVec ABI
+enhancements.
+
 @item -mfull-toc
 @itemx -mno-fp-in-toc
 @itemx -mno-sum-in-toc
@@ -6912,6 +6923,12 @@ Linux-based GNU system.
 On System V.4 and embedded PowerPC systems compile code for the
 NetBSD operating system.
 
+@item -mabi=altivec
+@opindex mabi=altivec
+Extend the current ABI with AltiVec ABI extensions.  This does not
+change the default ABI, instead it adds the AltiVec ABI extensions to
+the current ABI@.
+
 @item -mprototype
 @itemx -mno-prototype
 @opindex mprototype