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



> From: Aldy Hernandez <aldyh@redhat.com>
> Cc: gcc@gcc.gnu.org
> Date: 31 Oct 2001 15:36:01 -0500
> 
> 
> > 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....

Some generic comments:

- There seems to be no documentation for the patch
- You didn't say how you tested it---I'm not so worried if the Altivec
  part doesn't work, but I would like some reassurance it doesn't
  break, say, the powerpc-linux bootstrap.
- Patches should go to gcc-patches
- I'll comment on the parts of the patch that don't involve a zillion
  builtins, and on the first builtin.  Could you re-submit the patch
  with the more generic part split out?  The individual builtins are
  pretty boring from an approval point of view, it's the rest of the
  patch that needs care.

There are more specific comments below.  The bits I didn't comment on
are the bits I liked, which you'll notice is most of it :-).

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.

> 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.")},		\

You have an -maltivec but no -mno-altivec.

>     {"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

Sigh.  The comment is wrong.  You can't change this at all because it
changes the ABI.  Thus this needs to be ABI-dependent.

>   /* 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  \
> ! }

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]