This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: contributing altivec changes



On Wednesday, October 31, 2001, at 01:01 PM, Geoff Keating wrote:
>> From: Aldy Hernandez <aldyh@redhat.com>

> Shouldn't there be changes to the various alignment macros?  Altivec
> operands _must_ be 128-bit aligned, or they won't work, that means the
> stack must also be 128-bit aligned.

There definitely need to be changes here.

>> *** 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  \
>> ! }
>
> Likewise, this changes the ABI, so must be ABI-dependent.  You can't
> add new call-saved registers to an ABI.






>>   #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)
>> ))
>
> You might find that this looks better if you remove the parentheses
> around '(ALTIVEC_REGNO_P ... ? ... : )', but it's only an aesthetic issue.
>
>> ! #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.  */
>
> You should probably update the comments here and below.
>
>> ! #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)				\
>
> I think we're trying to standardize on a space after the !, like:
>
>        && ! 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},	\
>
> missing space...
>
>> +   {"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}},					   \
>
> missing space...
>
>>     {"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.
>>
>
>
> --
> - Geoffrey Keating <geoffk@geoffk.org> <geoffk@redhat.com>
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]