From: Aldy Hernandez Date: Wed, 7 Nov 2001 20:49:41 +0000 (+0000) Subject: invoke.texi: Add -maltivec, -mno-altivec, and -mabi=altivec for rs6000. X-Git-Tag: prereleases/libstdc++-3.0.95~1120 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=0ac081f6b81bb06d2a6a12349f6b32d503a65716;p=thirdparty%2Fgcc.git invoke.texi: Add -maltivec, -mno-altivec, and -mabi=altivec for rs6000. * 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 --- diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h index d807ee2a9db2..ae3b9c639077 100644 --- a/gcc/config/rs6000/aix.h +++ b/gcc/config/rs6000/aix.h @@ -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))) diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 3c7b2c0a3701..0cf9b9c46aa8 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -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)); /* 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 @@ -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; /* 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); + } +} + /* 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) diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h index 47b97c73e7b8..a5fa10b5b27e 100644 --- a/gcc/config/rs6000/rs6000.h +++ b/gcc/config/rs6000/rs6000.h @@ -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))) @@ -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 +}; diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 3d13a82fa7c8..5c3191a21176 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -37,7 +37,7 @@ ;; 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). @@ -13361,3 +13361,936 @@ 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")]) diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h index a6f79a1dc501..fcff961c90db 100644 --- a/gcc/config/rs6000/sysv4.h +++ b/gcc/config/rs6000/sysv4.h @@ -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. */ diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index b5e864e61dc4..9ad11f4232c1 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -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