This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: contributing altivec changes
> Yes, submit the infrastructure patches first, broken down into
> individual pieces for each logical change. Especially any parts that
> touch the generic parts of the compiler
great! and here it is....
2001-10-29 Aldy Hernandez <aldyh@redhat.com>
* rs6000.md (altivec_lvx): New.
(type): Add altivec attribute.
(*altivec_vec_move): New.
(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.
snip-- 105 builtins deleted. :)
* 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.
(altivec_register): New.
(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.
* rs6000.h (MASK_ALTIVEC): New.
(TARGET_ALTIVEC): New.
(TARGET_SWITCHES): Add altivec.
(FIRST_PSEUDO_REGISTER): Change to 109.
(DWARF_FRAME_REGISTERS): Same.
(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.
(PREDICATE_CODES): Add altivec_register.
Index: rs6000.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.130
diff -c -p -r1.130 rs6000.h
*** rs6000.h 2001/10/02 03:36:44 1.130
--- rs6000.h 2001/10/31 20:22:54
*************** extern int target_flags;
*** 209,214 ****
--- 209,217 ----
/* Nonzero if we need to schedule the prolog and epilog. */
#define MASK_SCHED_PROLOG 0x00040000
+ /* Use AltiVec instructions. */
+ #define MASK_ALTIVEC 0x00080000
+
#define TARGET_POWER (target_flags & MASK_POWER)
#define TARGET_POWER2 (target_flags & MASK_POWER2)
#define TARGET_POWERPC (target_flags & MASK_POWERPC)
*************** extern int target_flags;
*** 227,232 ****
--- 230,236 ----
#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_32BIT (! TARGET_64BIT)
#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT)
*************** extern int target_flags;
*** 282,287 ****
--- 286,293 ----
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.")}, \
{"new-mnemonics", MASK_NEW_MNEMONICS, \
N_("Use new mnemonics for PowerPC architecture")},\
{"old-mnemonics", -MASK_NEW_MNEMONICS, \
*************** extern int rs6000_debug_arg; /* debug a
*** 505,510 ****
--- 511,517 ----
#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"
*************** extern int rs6000_debug_arg; /* debug a
*** 634,644 ****
a register, in order to work around problems in allocating stack storage
in inline functions. */
! #define FIRST_PSEUDO_REGISTER 77
/* This must not decrease, for backwards compatibility. If
FIRST_PSEUDO_REGISTER increases, this should as well. */
! #define DWARF_FRAME_REGISTERS 77
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
--- 641,651 ----
a register, in order to work around problems in allocating stack storage
in inline functions. */
! #define FIRST_PSEUDO_REGISTER 109
/* This must not decrease, for backwards compatibility. If
FIRST_PSEUDO_REGISTER increases, this should as well. */
! #define DWARF_FRAME_REGISTERS 109
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
*************** extern int rs6000_debug_arg; /* debug a
*** 654,661 ****
{0, 1, FIXED_R2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FIXED_R13, 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, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1}
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
--- 661,672 ----
{0, 1, FIXED_R2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, FIXED_R13, 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, 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 \
! }
/* 1 for registers not available across function calls.
These must include the FIXED_REGISTERS and also any
*************** extern int rs6000_debug_arg; /* debug a
*** 669,675 ****
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}
#define MQ_REGNO 64
#define CR0_REGNO 68
--- 680,690 ----
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, \
! /* AltiVec registers. */ \
! 0, 0, 1, 0, 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 \
! }
#define MQ_REGNO 64
#define CR0_REGNO 68
*************** extern int rs6000_debug_arg; /* debug a
*** 679,684 ****
--- 694,701 ----
#define CR4_REGNO 72
#define MAX_CR_REGNO 75
#define XER_REGNO 76
+ #define FIRST_ALTIVEC_REGNO 77
+ #define LAST_ALTIVEC_REGNO 108
/* List the order in which to allocate registers. Each register must be
listed once, even those in FIXED_REGISTERS.
*************** extern int rs6000_debug_arg; /* debug a
*** 701,708 ****
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) */
#define REG_ALLOC_ORDER \
{32, \
45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, \
--- 718,734 ----
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)
+ 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, \
45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, \
*************** extern int rs6000_debug_arg; /* debug a
*** 716,722 ****
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}
/* True if register is floating-point. */
#define FP_REGNO_P(N) ((N) >= 32 && (N) <= 63)
--- 742,755 ----
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, \
! /* 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)
*************** extern int rs6000_debug_arg; /* debug a
*** 733,738 ****
--- 766,774 ----
/* 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
*************** extern int rs6000_debug_arg; /* debug a
*** 744,751 ****
#define HARD_REGNO_NREGS(REGNO, MODE) \
(FP_REGNO_P (REGNO) \
? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
! : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
/* 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
--- 780,802 ----
#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
*************** extern int rs6000_debug_arg; /* debug a
*** 757,762 ****
--- 808,814 ----
(GET_MODE_CLASS (MODE) == MODE_FLOAT \
|| (GET_MODE_CLASS (MODE) == MODE_INT \
&& GET_MODE_SIZE (MODE) == UNITS_PER_FP_WORD)) \
+ : ALTIVEC_VECTOR_MODE (MODE) ? ALTIVEC_REGNO_P (REGNO) \
: 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 \
*************** extern int rs6000_debug_arg; /* debug a
*** 776,781 ****
--- 828,837 ----
? 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
*************** extern int rs6000_debug_arg; /* debug a
*** 788,793 ****
--- 844,850 ----
((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) == SPECIAL_REGS || (CLASS1) == MQ_REGS \
|| (CLASS1) == LINK_REGS || (CLASS1) == CTR_REGS \
|| (CLASS1) == LINK_OR_CTR_REGS) \
*************** enum reg_class
*** 912,917 ****
--- 969,975 ----
BASE_REGS,
GENERAL_REGS,
FLOAT_REGS,
+ ALTIVEC_REGS,
NON_SPECIAL_REGS,
MQ_REGS,
LINK_REGS,
*************** enum reg_class
*** 937,942 ****
--- 995,1001 ----
"BASE_REGS", \
"GENERAL_REGS", \
"FLOAT_REGS", \
+ "ALTIVEC_REGS", \
"NON_SPECIAL_REGS", \
"MQ_REGS", \
"LINK_REGS", \
*************** enum reg_class
*** 955,978 ****
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 */ \
}
/* The same information, inverted:
--- 1014,1038 ----
This is an initializer for a vector of HARD_REG_SET
of length N_REG_CLASSES. */
! #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, 0xfffe0000, 0x0001ffff }, /* ALTIVEC_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:
*************** enum reg_class
*** 984,989 ****
--- 1044,1050 ----
((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 \
*************** enum reg_class
*** 1006,1011 ****
--- 1067,1073 ----
: (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 \
*************** enum reg_class
*** 1103,1113 ****
#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. */
! #define SECONDARY_MEMORY_NEEDED(CLASS1,CLASS2,MODE) \
! ((CLASS1) != (CLASS2) && ((CLASS1) == FLOAT_REGS || (CLASS2) == FLOAT_REGS))
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.
--- 1165,1178 ----
#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
secondary_reload_class (CLASS, MODE, IN)
! /* 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 \
! || (CLASS1) == ALTIVEC_REGS \
! || (CLASS2) == ALTIVEC_REGS))
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.
*************** typedef struct rs6000_stack {
*** 1294,1309 ****
&& TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
|| POINTER_TYPE_P (VALTYPE) \
? word_mode : TYPE_MODE (VALTYPE), \
! 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))
/* The definition of this macro implies that there are cases where
a scalar value cannot be returned in registers.
--- 1359,1376 ----
&& TYPE_PRECISION (VALTYPE) < BITS_PER_WORD) \
|| POINTER_TYPE_P (VALTYPE) \
? word_mode : TYPE_MODE (VALTYPE), \
! 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, 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.
*************** typedef struct rs6000_stack {
*** 1338,1346 ****
--- 1405,1419 ----
? 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 77
+ #define ALTIVEC_ARG_MAX_REG 108
+ #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 79
/* Flags for the call/call_value rtl operations set up by function_arg */
#define CALL_NORMAL 0x00000000 /* no special processing */
*************** typedef struct rs6000_stack {
*** 1353,1364 ****
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))
/* 1 if N is a possible register number for function argument passing.
On RS/6000, these are r3-r10 and fp1-fp13. */
#define FUNCTION_ARG_REGNO_P(N) \
((unsigned)(((N) - GP_ARG_MIN_REG) < (unsigned)(GP_ARG_NUM_REG)) \
|| ((unsigned)((N) - FP_ARG_MIN_REG) < (unsigned)(FP_ARG_NUM_REG)))
--- 1426,1440 ----
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) \
! || ((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. */
#define FUNCTION_ARG_REGNO_P(N) \
((unsigned)(((N) - GP_ARG_MIN_REG) < (unsigned)(GP_ARG_NUM_REG)) \
+ || ((unsigned)((N) - ALTIVEC_ARG_MIN_REG) < (unsigned)(ALTIVEC_ARG_MAX_REG)) \
|| ((unsigned)((N) - FP_ARG_MIN_REG) < (unsigned)(FP_ARG_NUM_REG)))
*************** typedef struct rs6000_args
*** 1778,1783 ****
--- 1854,1860 ----
&& 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) \
&& (((MODE) != DFmode && (MODE) != DImode) \
|| (TARGET_32BIT \
? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 4) \
*************** typedef struct rs6000_args
*** 1805,1810 ****
--- 1882,1888 ----
&& ! 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 \
*************** extern char rs6000_reg_names[][8]; /* re
*** 2389,2394 ****
--- 2467,2505 ----
&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 */ \
}
/* print-rtl can't handle the above REGISTER_NAMES, so define the
*************** extern char rs6000_reg_names[][8]; /* re
*** 2407,2413 ****
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \
"mq", "lr", "ctr", "ap", \
"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
! "xer" \
}
/* Table of additional register names to use in user input. */
--- 2518,2528 ----
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", \
"mq", "lr", "ctr", "ap", \
"cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", \
! "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" \
}
/* Table of additional register names to use in user input. */
*************** extern char rs6000_reg_names[][8]; /* re
*** 2429,2434 ****
--- 2544,2557 ----
{"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}, \
/* no additional names for: mq, lr, ctr, ap */ \
{"cr0", 68}, {"cr1", 69}, {"cr2", 70}, {"cr3", 71}, \
{"cr4", 72}, {"cr5", 73}, {"cr6", 74}, {"cr7", 75}, \
*************** do { \
*** 2617,2622 ****
--- 2740,2746 ----
GT, LEU, LTU, GEU, GTU}}, \
{"boolean_operator", {AND, IOR, XOR}}, \
{"boolean_or_operator", {IOR, XOR}}, \
+ {"altivec_register", {REG,SUBREG}}, \
{"min_max_operator", {SMIN, SMAX, UMIN, UMAX}},
/* uncomment for disabling the corresponding default options */
*************** extern int flag_pic;
*** 2629,2631 ****
--- 2753,2868 ----
extern int optimize;
extern int flag_expensive_optimizations;
extern int frame_pointer_needed;
+
+ enum rs6000_builtins
+ {
+ /* AltiVec builtins. */
+ ALTIVEC_BUILTIN_ST_INTERNAL,
+ ALTIVEC_BUILTIN_LD_INTERNAL,
+ ALTIVEC_BUILTIN_VADDUBM,
+ ALTIVEC_BUILTIN_VADDUHM,
+ ALTIVEC_BUILTIN_VADDUWM,
+ ALTIVEC_BUILTIN_VADDFP,
+ ALTIVEC_BUILTIN_VADDCUW,
+ ALTIVEC_BUILTIN_VADDUBS,
+ ALTIVEC_BUILTIN_VADDSBS,
+ ALTIVEC_BUILTIN_VADDUHS,
+ ALTIVEC_BUILTIN_VADDSHS,
+ ALTIVEC_BUILTIN_VADDUWS,
+ ALTIVEC_BUILTIN_VADDSWS,
+ ALTIVEC_BUILTIN_VAND,
+ ALTIVEC_BUILTIN_VANDC,
+ ALTIVEC_BUILTIN_VAVGUB,
+ ALTIVEC_BUILTIN_VAVGSB,
+ ALTIVEC_BUILTIN_VAVGUH,
+ ALTIVEC_BUILTIN_VAVGSH,
+ ALTIVEC_BUILTIN_VAVGUW,
+ ALTIVEC_BUILTIN_VAVGSW,
+ ALTIVEC_BUILTIN_VCMPBFP,
+ ALTIVEC_BUILTIN_VCMPEQUB,
+ ALTIVEC_BUILTIN_VCMPEQUH,
+ ALTIVEC_BUILTIN_VCMPEQUW,
+ ALTIVEC_BUILTIN_VCMPEQFP,
+ ALTIVEC_BUILTIN_VCMPGEFP,
+ ALTIVEC_BUILTIN_VCMPGTUB,
+ ALTIVEC_BUILTIN_VCMPGTSB,
+ ALTIVEC_BUILTIN_VCMPGTUH,
+ ALTIVEC_BUILTIN_VCMPGTSH,
+ ALTIVEC_BUILTIN_VCMPGTUW,
+ ALTIVEC_BUILTIN_VCMPGTSW,
+ ALTIVEC_BUILTIN_VCMPGTFP,
+ ALTIVEC_BUILTIN_VMAXUB,
+ ALTIVEC_BUILTIN_VMAXSB,
+ ALTIVEC_BUILTIN_VMAXUH,
+ ALTIVEC_BUILTIN_VMAXSH,
+ ALTIVEC_BUILTIN_VMAXUW,
+ ALTIVEC_BUILTIN_VMAXSW,
+ ALTIVEC_BUILTIN_VMAXFP,
+ ALTIVEC_BUILTIN_VMRGHB,
+ ALTIVEC_BUILTIN_VMRGHH,
+ ALTIVEC_BUILTIN_VMRGHW,
+ ALTIVEC_BUILTIN_VMRGLB,
+ ALTIVEC_BUILTIN_VMRGLH,
+ ALTIVEC_BUILTIN_VMRGLW,
+ ALTIVEC_BUILTIN_VMINUB,
+ ALTIVEC_BUILTIN_VMINSB,
+ ALTIVEC_BUILTIN_VMINUH,
+ ALTIVEC_BUILTIN_VMINSH,
+ ALTIVEC_BUILTIN_VMINUW,
+ ALTIVEC_BUILTIN_VMINSW,
+ ALTIVEC_BUILTIN_VMINFP,
+ ALTIVEC_BUILTIN_VMULEUB,
+ ALTIVEC_BUILTIN_VMULESB,
+ ALTIVEC_BUILTIN_VMULEUH,
+ ALTIVEC_BUILTIN_VMULESH,
+ ALTIVEC_BUILTIN_VMULOUB,
+ ALTIVEC_BUILTIN_VMULOSB,
+ ALTIVEC_BUILTIN_VMULOUH,
+ ALTIVEC_BUILTIN_VMULOSH,
+ ALTIVEC_BUILTIN_VNOR,
+ ALTIVEC_BUILTIN_VOR,
+ ALTIVEC_BUILTIN_VPKUHUM,
+ ALTIVEC_BUILTIN_VPKUWUM,
+ ALTIVEC_BUILTIN_VPKPX,
+ ALTIVEC_BUILTIN_VPKUHSS,
+ ALTIVEC_BUILTIN_VPKSHSS,
+ ALTIVEC_BUILTIN_VPKUWSS,
+ ALTIVEC_BUILTIN_VPKSWSS,
+ ALTIVEC_BUILTIN_VPKUHUS,
+ ALTIVEC_BUILTIN_VPKSHUS,
+ ALTIVEC_BUILTIN_VPKUWUS,
+ ALTIVEC_BUILTIN_VPKSWUS,
+ ALTIVEC_BUILTIN_VRLB,
+ ALTIVEC_BUILTIN_VRLH,
+ ALTIVEC_BUILTIN_VRLW,
+ ALTIVEC_BUILTIN_VSLB,
+ ALTIVEC_BUILTIN_VSLH,
+ ALTIVEC_BUILTIN_VSLW,
+ ALTIVEC_BUILTIN_VSL,
+ ALTIVEC_BUILTIN_VSLO,
+ ALTIVEC_BUILTIN_VSRB,
+ ALTIVEC_BUILTIN_VRSH,
+ ALTIVEC_BUILTIN_VRSW,
+ ALTIVEC_BUILTIN_VSRAB,
+ ALTIVEC_BUILTIN_VSRAH,
+ ALTIVEC_BUILTIN_VSRAW,
+ ALTIVEC_BUILTIN_VSR,
+ ALTIVEC_BUILTIN_VSRO,
+ ALTIVEC_BUILTIN_VSUBUBM,
+ ALTIVEC_BUILTIN_VSUBUHM,
+ ALTIVEC_BUILTIN_VSUBUWM,
+ ALTIVEC_BUILTIN_VSUBFP,
+ ALTIVEC_BUILTIN_VSUBCUW,
+ ALTIVEC_BUILTIN_VSUBUBS,
+ ALTIVEC_BUILTIN_VSUBSBS,
+ ALTIVEC_BUILTIN_VSUBUHS,
+ ALTIVEC_BUILTIN_VSUBSHS,
+ ALTIVEC_BUILTIN_VSUBUWS,
+ ALTIVEC_BUILTIN_VSUBSWS,
+ ALTIVEC_BUILTIN_VSUM4UBS,
+ ALTIVEC_BUILTIN_VSUM4SBS,
+ ALTIVEC_BUILTIN_VSUM4SHS,
+ ALTIVEC_BUILTIN_VSUM2SWS,
+ ALTIVEC_BUILTIN_VSUMSWS,
+ ALTIVEC_BUILTIN_VXOR
+ };
Index: rs6000.c
===================================================================
RCS file: /cvs/uberbaum/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.224
diff -c -p -r1.224 rs6000.c
*** rs6000.c 2001/10/31 14:08:09 1.224
--- rs6000.c 2001/10/31 20:22:16
*************** static int rs6000_adjust_cost PARAMS ((r
*** 146,151 ****
--- 146,157 ----
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));
+
/* Default register names. */
char rs6000_reg_names[][8] =
*************** char rs6000_reg_names[][8] =
*** 160,166 ****
"24", "25", "26", "27", "28", "29", "30", "31",
"mq", "lr", "ctr","ap",
"0", "1", "2", "3", "4", "5", "6", "7",
! "xer"
};
#ifdef TARGET_REGNAMES
--- 166,177 ----
"24", "25", "26", "27", "28", "29", "30", "31",
"mq", "lr", "ctr","ap",
"0", "1", "2", "3", "4", "5", "6", "7",
! "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"
};
#ifdef TARGET_REGNAMES
*************** static const char alt_reg_names[][8] =
*** 176,182 ****
"%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",
"mq", "lr", "ctr", "ap",
"%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7",
! "xer"
};
#endif
--- 187,198 ----
"%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",
"mq", "lr", "ctr", "ap",
"%cr0", "%cr1", "%cr2", "%cr3", "%cr4", "%cr5", "%cr6", "%cr7",
! "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"
};
#endif
*************** static const char alt_reg_names[][8] =
*** 205,210 ****
--- 221,232 ----
#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
*************** input_operand (op, mode)
*** 1411,1416 ****
--- 1433,1451 ----
return 0;
}
+ /* Return 1 if this is an AltiVec vector register. */
+ int
+ altivec_register (x, mode)
+ rtx x;
+ enum machine_mode mode;
+ {
+ if (register_operand (x, mode)
+ && ALTIVEC_VECTOR_MODE (GET_MODE (x)))
+ return 1;
+
+ return 0;
+ }
+
/* Return 1 for an operand in small memory on V.4/eabi. */
int
*************** rs6000_legitimize_address (x, oldx, mode
*** 1544,1550 ****
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
--- 1579,1585 ----
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
*************** rs6000_legitimize_address (x, oldx, mode
*** 1570,1575 ****
--- 1605,1622 ----
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
*************** rs6000_emit_move (dest, source, mode)
*** 1862,1867 ****
--- 1909,1923 ----
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 */
*************** rs6000_va_arg (valist, type)
*** 2838,2843 ****
--- 2894,3322 ----
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)));
+
+ 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. */
+
+ /* int, float, float. */
+ else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == V4SFmode)
+ type = v4si_ftype_v4sf_v4sf;
+
+ /* short, char, char. */
+ else if (mode0 == V8HImode && mode1 == V16QImode && mode2 == V16QImode)
+ type = v8hi_ftype_v16qi_v16qi;
+
+ /* int, short, short. */
+ else if (mode0 == V4SImode && mode0 == V8HImode && mode1 == V8HImode)
+ type = v4si_ftype_v8hi_v8hi;
+
+ /* short, int, int. */
+ else if (mode0 == V8HImode && mode1 == V4SImode && mode2 == V4SImode)
+ type = v8hi_ftype_v4si_v4si;
+
+ /* char, short, short. */
+ else if (mode0 == V16QImode && mode1 == V8HImode && mode2 == V8HImode)
+ type = v16qi_ftype_v8hi_v8hi;
+
+ /* int, char, int. */
+ else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V4SImode)
+ type = v4si_ftype_v16qi_v4si;
+
+ /* int, short, int. */
+ else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V4SImode)
+ type = v4si_ftype_v8hi_v4si;
+
+ 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. */
*************** secondary_reload_class (class, mode, in)
*** 3941,3946 ****
--- 4420,4430 ----
&& (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))
*************** print_operand (file, x, code)
*** 4714,4719 ****
--- 5198,5229 ----
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 (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG)
+ {
+ if (REGNO (XEXP (x, 0)) == 0)
+ fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 1)) ],
+ reg_names[ REGNO (XEXP (x, 0)) ]);
+ else
+ fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 0)) ],
+ reg_names[ REGNO (XEXP (x, 1)) ]);
+ }
+ else
+ abort ();
+ break;
+ }
case 0:
if (GET_CODE (x) == REG)
Index: rs6000.md
===================================================================
RCS file: /cvs/uberbaum/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.128
diff -c -p -r1.128 rs6000.md
*** rs6000.md 2001/10/16 00:43:21 1.128
--- rs6000.md 2001/10/31 20:24:04
***************
*** 37,43 ****
;; 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"
(const_string "integer"))
;; Length (in bytes).
--- 37,43 ----
;; 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,altivec"
(const_string "integer"))
;; Length (in bytes).
***************
*** 13359,13361 ****
--- 13359,14299 ----
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")])
+
+ ;; No code is needed to copy between vector registers.
+ (define_insn "*altivec_vec_move"
+ [(set (match_operand 0 "altivec_register" "=v")
+ (match_operand 1 "altivec_register" "v"))]
+ "TARGET_ALTIVEC"
+ ""
+ [(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")
+ (match_operand:V4SI 1 "input_operand" "v,m"))]
+ "TARGET_ALTIVEC"
+ "@
+ stvx\t%1,%y0
+ ldvx\t%0,%y1"
+ [(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")
+ (match_operand:V8HI 1 "input_operand" "v,m"))]
+ "TARGET_ALTIVEC"
+ "@
+ stvx\t%1,%y0
+ ldvx\t%0,%y1"
+ [(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")
+ (match_operand:V16QI 1 "input_operand" "v,m"))]
+ "TARGET_ALTIVEC"
+ "@
+ stvx\t%1,%y0
+ ldvx\t%0,%y1"
+ [(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")
+ (match_operand:V4SF 1 "input_operand" "v,m"))]
+ "TARGET_ALTIVEC"
+ "@
+ stvx\t%1,%y0
+ ldvx\t%0,%y1"
+ [(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")])
+
snip-- 100 builtins deleted.