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: altivec patches


hi guys.

After a few iterations I think this is finally it-- for the first
batch of patches anyhow.

Geoff and I had a couple iterations in private to get the alignment
things sorted out, but everything that was suggested has been
implemented: vrsave in bit patterns, alignment, v=v move, etc etc.

I will be working on stack stuff (epilogue, prologue, stack frame,
vrsave) in the next couple days and I wanted to get these standalone
patches in first.

What is left?

        - stack stuff
        - DWARF_FRAME_REGISTERS (unwind-dw2.c work)
        - varargs
        - rest of builtins
        - function units
        - testcases

ok to install now?  I am bootstraping and checking for regressions
again-- assuming these are ok.

Aldy

2001-11-05  Aldy Hernandez  <aldyh@redhat.com>

	* doc/invoke.texi: Add -maltivec, -mno-altivec, and -mabi=altivec
	for rs6000.

	* config/rs6000/rs6000.h (MASK_ALTIVEC): New.
	(TARGET_ALTIVEC): New.
	(TARGET_SWITCHES): Add altivec.
	(FIRST_PSEUDO_REGISTER): Change to 109.
	(CALL_USED_REGISTERS): Same.
	(FIRST_ALTIVEC_REGNO): New.
	(LAST_ALTIVEC_REGNO): New.
	(ALTIVEC_REGNO_P): New.
	(UNITS_PER_ALTIVEC_WORD): New.
	(ALTIVEC_VECTOR_MODE): New.
	(FIXED_REGISTERS): Add altivec registers.
	(REG_ALLOC_ORDER): Same.
	(HARD_REGNO_NREGS): Adjust for altivec registers.
	(HARD_REGNO_MODE_OK): Same.
	(MODES_TIEABLE_P): Same.
	(REGISTER_MOVE_COST): Same.
	(REGNO_REG_CLASS): Same.
	(reg_class): Add ALTIVEC_REGS.
	(REG_CLASS_NAMES): Same.
	(REG_CLASS_CONTENTS): Same.
	(REG_CLASS_FROM_LETTER): Add 'v' constraint for ALTIVEC_REGS.
	(ALTIVEC_ARG_RETURN): New.
	(FUNCTION_VALUE): Handle VECTOR_TYPE.
	(LIBCALL_VALUE): Handle altivec vector modes.
	(VECTOR_MODE_SUPPORTED_P): New.
	(ALTIVEC_ARG_MIN_REG): New.
	(ALTIVEC_ARG_MAX_REG): New.
	(ALTIVEC_ARG_NUM_REG): New.
	(FUNCTION_VALUE_REGNO_P): Return true for altivec return register.
	(FUNCTION_ARG_REGNO_P): Support passing args in altivec registers.
	(REGISTER_NAMES): Add altivec regs.
	(DEBUG_REGISTER_NAMES): Same.
	(ADDITIONAL_REGISTER_NAMES): Same.
	(rs6000_builtins): New.
	(MD_EXPAND_BUILTIN): New.
	(MD_INIT_BUILTINS): New.
	(LEGITIMATE_OFFSET_ADDRESS_P): This addressing mode is not valid
	for AltiVec instructions.
	(LEGITIMATE_LO_SUM_ADDRESS_P): Same.
	(HARD_REGNO_MODE_OK): Altivec modes can only go in altivec
	registers.
	(SECONDARY_MEMORY_NEEDED): We need memory to copy vector modes.
	(TARGET_SWITCHES): Add no-altivec.
	(DATA_ALIGNMENT): Align vectors to 128 bits.
	(TARGET_OPTIONS): Add abi= option.
	Add rs6000_abi_string extern.
	(LOCAL_ALIGNMENT): New.
	(CPP_CPU_SPEC): Define __ALTIVEC__ when -maltivec.
	(MASK_ALTIVEC_ABI): New.
	(TARGET_ALTIVEC_ABI): New.
	(CONDITIONAL_REGISTER_USAGE): Set first 20 AltiVec registers to
	call-saved.
	(STACK_BOUNDARY): Adjust for altivec.
	(BIGGEST_ALIGNMENT): Same.
	(rs6000_args): Add vregno.
	(USE_ALTIVEC_FOR_ARG_P): New.
	(FIXED_REGISTERS): Add vrsave register.
	(CALL_USED_REGISTERS): Same.
	(CONDITIONAL_REGISTER_USAGE): Set VRSAVE info.
	(VRSAVE_REGNO): New.
	(reg_class): Add VRSAVE_REGS.
	(REG_CLASS_NAMES): Same.
	(REG_CLASS_CONTENTS): Same.
	(REGNO_REG_CLASS): Same.
	
	* config/rs6000/sysv4.h (STACK_BOUNDARY): Adjust for altivec.
	(ABI_STACK_BOUNDARY): Same.
	(BIGGEST_ALIGNMENT): Same.
	(ADJUST_FIELD_ALIGN): Remove undef.  Define anew.
	(ROUND_TYPE_ALIGN): Same.
	
	* config/rs6000/rs6000.c (rs6000_expand_builtin): New.
	(altivec_expand_builtin): New.
	(altivec_init_builtins): New.
	(TARGET_EXPAND_BUILTIN): New.
	(TARGET_INIT_BUILTINS): New.
	(rs6000_init_builtins): New.
	(struct builtin_description): New.
	(bdesc_2arg): New.
	(rs6000_reg_names): Add altivec registers.
	(alt_reg_names): Same.
	(secondary_reload_class): Altivec regs can hold altivec regs and
	memory.
	(rs6000_emit_move): Force constants into memory for AltiVec moves.
	(print_operand): Add 'y' case for printing altivec memory
	operands.
	(rs6000_legitimize_address): Legitimize vector addresses into
	[REG+REG] or [REG].
	(altivec_expand_binop_builtin): New.
	New string rs6000_current_abi.
	(rs6000_override_options): Call rs6000_parse_abi_options.
	(rs6000_parse_abi_options): New.
	(function_arg_boundary): Vector arguments must be 16
	byte aligned.
	(function_arg_advance): Handle vector arguments.
	(function_arg_partial_nregs): Same.
	(init_cumulative_args): Same.
	(function_arg): Same.

	* config/rs6000/rs6000.md (altivec_lvx): New.
	(type): Add altivec attribute.
	(movv4si): New.
	(*movv4si_internal): New.
	(movv16qi): New.
	(*movv16qi_internal): New.
	(movv8hi): New.
	(*movv8hi_internal1): New.
	(movv4sf): New.
	(*movv4sf_internal1): New.
	(altivec_stvx): New.
*builtins deleted*

	Index: doc/invoke.texi
===================================================================
RCS file: /cvs/uberbaum/gcc/doc/invoke.texi,v
retrieving revision 1.69
diff -c -p -r1.69 invoke.texi
*** invoke.texi	2001/10/28 19:12:12	1.69
--- invoke.texi	2001/11/06 22:24:35
*************** in the following sections.
*** 424,429 ****
--- 424,430 ----
  -mtune=@var{cpu-type} @gol
  -mpower  -mno-power  -mpower2  -mno-power2 @gol
  -mpowerpc  -mpowerpc64  -mno-powerpc @gol
+ -maltivec -mno-altivec @gol
  -mpowerpc-gpopt  -mno-powerpc-gpopt @gol
  -mpowerpc-gfxopt  -mno-powerpc-gfxopt @gol
  -mnew-mnemonics  -mold-mnemonics @gol
*************** in the following sections.
*** 436,441 ****
--- 437,443 ----
  -mno-relocatable  -mrelocatable-lib  -mno-relocatable-lib @gol
  -mtoc  -mno-toc -mlittle  -mlittle-endian  -mbig  -mbig-endian @gol
  -mcall-aix -mcall-sysv -mcall-netbsd @gol
+ -mabi=altivec @gol
  -mprototype  -mno-prototype @gol
  -msim  -mmvme  -mads  -myellowknife  -memb -msdata @gol
  -msdata=@var{opt}  -mvxworks -G @var{num}}
*************** values for @var{cpu_type} are used for @
*** 6677,6682 ****
--- 6679,6693 ----
  architecture, registers, and mnemonics set by @option{-mcpu}, but the
  scheduling parameters set by @option{-mtune}.
  
+ @item -maltivec
+ @itemx -mno-altivec
+ @opindex maltivec
+ @opindex mno-altivec
+ These switches enable or disable the use of built-in functions that
+ allow access to the AltiVec instruction set.  You may also need to set
+ @option{-mabi=altivec} to adjust the current ABI with AltiVec ABI
+ enhancements.
+ 
  @item -mfull-toc
  @itemx -mno-fp-in-toc
  @itemx -mno-sum-in-toc
*************** Linux-based GNU system.
*** 6904,6909 ****
--- 6915,6926 ----
  @opindex mcall-netbsd
  On System V.4 and embedded PowerPC systems compile code for the
  NetBSD operating system.
+ 
+ @item -mabi=altivec
+ @opindex mabi=altivec
+ Extend the current ABI with AltiVec ABI extensions.  This does not
+ change the default ABI, instead it adds the AltiVec ABI extensions to
+ the current ABI@
  
  @item -mprototype
  @itemx -mno-prototype
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/11/06 22:24:41
*************** Boston, MA 02111-1307, USA.  */
*** 83,89 ****
  %{mcpu=801: -D_ARCH_PPC} \
  %{mcpu=821: -D_ARCH_PPC} \
  %{mcpu=823: -D_ARCH_PPC} \
! %{mcpu=860: -D_ARCH_PPC}"
  
  /* Common ASM definitions used by ASM_SPEC among the various targets
     for handling -mcpu=xxx switches.  */
--- 83,90 ----
  %{mcpu=801: -D_ARCH_PPC} \
  %{mcpu=821: -D_ARCH_PPC} \
  %{mcpu=823: -D_ARCH_PPC} \
! %{mcpu=860: -D_ARCH_PPC} \
! %{maltivec: -D__ALTIVEC__}"
  
  /* Common ASM definitions used by ASM_SPEC among the various targets
     for handling -mcpu=xxx switches.  */
*************** extern int target_flags;
*** 209,214 ****
--- 210,221 ----
  /* Nonzero if we need to schedule the prolog and epilog.  */
  #define MASK_SCHED_PROLOG	0x00040000
  
+ /* Use AltiVec instructions.  */
+ #define MASK_ALTIVEC		0x00080000
+ 
+ /* Enhance the current ABI with AltiVec extensions.  */
+ #define MASK_ALTIVEC_ABI	0x00100000
+ 
  #define TARGET_POWER		(target_flags & MASK_POWER)
  #define TARGET_POWER2		(target_flags & MASK_POWER2)
  #define TARGET_POWERPC		(target_flags & MASK_POWERPC)
*************** extern int target_flags;
*** 227,232 ****
--- 234,241 ----
  #define TARGET_NO_UPDATE	(target_flags & MASK_NO_UPDATE)
  #define TARGET_NO_FUSED_MADD	(target_flags & MASK_NO_FUSED_MADD)
  #define TARGET_SCHED_PROLOG	(target_flags & MASK_SCHED_PROLOG)
+ #define TARGET_ALTIVEC		(target_flags & MASK_ALTIVEC)
+ #define TARGET_ALTIVEC_ABI	(target_flags & MASK_ALTIVEC_ABI)
  
  #define TARGET_32BIT		(! TARGET_64BIT)
  #define TARGET_HARD_FLOAT	(! TARGET_SOFT_FLOAT)
*************** extern int target_flags;
*** 282,287 ****
--- 291,300 ----
  			N_("Use PowerPC-64 instruction set")},		\
    {"no-powerpc64",	- MASK_POWERPC64,				\
  			N_("Don't use PowerPC-64 instruction set")},	\
+   {"altivec",		MASK_ALTIVEC,					\
+ 			N_("Use AltiVec instructions.")},		\
+   {"no-altivec",	- MASK_ALTIVEC,					\
+ 			N_("Don't use AltiVec instructions.")},	\
    {"new-mnemonics",	MASK_NEW_MNEMONICS,				\
  			N_("Use new mnemonics for PowerPC architecture")},\
    {"old-mnemonics",	-MASK_NEW_MNEMONICS,				\
*************** extern enum processor_type rs6000_cpu;
*** 409,414 ****
--- 422,428 ----
     {"tune=", &rs6000_select[2].string,					\
      N_("Schedule code for given CPU") },				\
     {"debug=", &rs6000_debug_name, N_("Enable debug output") },		\
+    {"abi=", &rs6000_abi_string, N_("Specify ABI to use") },		\
     SUBTARGET_OPTIONS							\
  }
  
*************** struct rs6000_cpu_select
*** 424,430 ****
  extern struct rs6000_cpu_select rs6000_select[];
  
  /* Debug support */
! extern const char *rs6000_debug_name;		/* Name for -mdebug-xxxx option */
  extern int rs6000_debug_stack;		/* debug stack applications */
  extern int rs6000_debug_arg;		/* debug argument handling */
  
--- 438,445 ----
  extern struct rs6000_cpu_select rs6000_select[];
  
  /* Debug support */
! extern const char *rs6000_debug_name;	/* Name for -mdebug-xxxx option */
! extern const char *rs6000_abi_string;	/* for -mabi={sysv,darwin,solaris,eabi,aix,altivec} */
  extern int rs6000_debug_stack;		/* debug stack applications */
  extern int rs6000_debug_arg;		/* debug argument handling */
  
*************** extern int rs6000_debug_arg;		/* debug a
*** 505,510 ****
--- 520,526 ----
  #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
*** 569,581 ****
  #define PARM_BOUNDARY (TARGET_32BIT ? 32 : 64)
  
  /* Boundary (in *bits*) on which stack pointer should be aligned.  */
! #define STACK_BOUNDARY (TARGET_32BIT ? 64 : 128)
  
  /* Allocation boundary (in *bits*) for the code of a function.  */
  #define FUNCTION_BOUNDARY 32
  
  /* No data type wants to be aligned rounder than this.  */
! #define BIGGEST_ALIGNMENT 64
  
  /* Handle #pragma pack.  */
  #define HANDLE_PRAGMA_PACK 1
--- 585,604 ----
  #define PARM_BOUNDARY (TARGET_32BIT ? 32 : 64)
  
  /* Boundary (in *bits*) on which stack pointer should be aligned.  */
! #define STACK_BOUNDARY ((TARGET_32BIT && !TARGET_ALTIVEC_ABI) ? 64 : 128)
  
  /* Allocation boundary (in *bits*) for the code of a function.  */
  #define FUNCTION_BOUNDARY 32
  
  /* No data type wants to be aligned rounder than this.  */
! #define BIGGEST_ALIGNMENT 128
! 
! /* A C expression to compute the alignment for a variables in the
!    local store.  TYPE is the data type, and ALIGN is the alignment
!    that the object would ordinarily have.  */
! #define LOCAL_ALIGNMENT(TYPE, ALIGN)				\
! 	((TARGET_ALTIVEC		    			\
! 	  && TREE_CODE (TYPE)) == VECTOR_TYPE ? 128 : ALIGN)
  
  /* Handle #pragma pack.  */
  #define HANDLE_PRAGMA_PACK 1
*************** extern int rs6000_debug_arg;		/* debug a
*** 594,602 ****
    (TREE_CODE (EXP) == STRING_CST	\
     && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
  
! /* Make arrays of chars word-aligned for the same reasons.  */
  #define DATA_ALIGNMENT(TYPE, ALIGN)		\
!   (TREE_CODE (TYPE) == ARRAY_TYPE		\
     && TYPE_MODE (TREE_TYPE (TYPE)) == QImode	\
     && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
  
--- 617,627 ----
    (TREE_CODE (EXP) == STRING_CST	\
     && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
  
! /* Make arrays of chars word-aligned for the same reasons.
!    Align vectors to 128 bits.  */
  #define DATA_ALIGNMENT(TYPE, ALIGN)		\
!   (TREE_CODE (TYPE) == VECTOR_TYPE ? 128	\
!    : TREE_CODE (TYPE) == ARRAY_TYPE		\
     && TYPE_MODE (TREE_TYPE (TYPE)) == QImode	\
     && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
  
*************** extern int rs6000_debug_arg;		/* debug a
*** 634,643 ****
     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
--- 659,670 ----
     a register, in order to work around problems in allocating stack storage
     in inline functions.  */
  
! #define FIRST_PSEUDO_REGISTER 110
  
  /* This must not decrease, for backwards compatibility.  If
     FIRST_PSEUDO_REGISTER increases, this should as well.  */
+ /* fixme: this needs to be defined to "TARGET_ALTIVEC_ABI ? 110 : 77"
+    and then fix usages of DWARF_FRAME_REGISTERS to work.  */
  #define DWARF_FRAME_REGISTERS 77
  
  /* 1 for registers that have pervasive standard uses
*************** extern int rs6000_debug_arg;		/* debug a
*** 655,661 ****
     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
--- 682,693 ----
     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, \
!    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,676 ****
     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
  #define CR1_REGNO    69
--- 701,714 ----
     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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
!    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
!    0						   \
! }
  
+ 
  #define MQ_REGNO     64
  #define CR0_REGNO    68
  #define CR1_REGNO    69
*************** extern int rs6000_debug_arg;		/* debug a
*** 679,684 ****
--- 717,725 ----
  #define CR4_REGNO    72
  #define MAX_CR_REGNO 75
  #define XER_REGNO    76
+ #define FIRST_ALTIVEC_REGNO	77
+ #define LAST_ALTIVEC_REGNO	108
+ #define VRSAVE_REGNO		109
  
  /* List the order in which to allocate registers.  Each register must be
     listed once, even those in FIXED_REGISTERS.
*************** extern int rs6000_debug_arg;		/* debug a
*** 701,707 ****
  	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, 							\
--- 742,757 ----
  	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, vrsave (fixed)
! 
! 	AltiVec registers:
! 	v0 - v1         (not saved or used for anything)
! 	v13 - v3        (not saved; incoming vector arg registers)
! 	v2              (not saved; incoming vector arg reg; return value)
! 	v19 - v14       (not saved or used for anything)
! 	v31 - v20       (saved; order given to save least number)
! */
! 						
  
  #define REG_ALLOC_ORDER					\
    {32, 							\
*************** 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)
--- 766,779 ----
     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 ****
--- 790,798 ----
  /* 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 ****
--- 804,826 ----
  #define HARD_REGNO_NREGS(REGNO, MODE)					\
    (FP_REGNO_P (REGNO)							\
     ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
+    : ALTIVEC_REGNO_P (REGNO)						\
+    ? ((GET_MODE_SIZE (MODE) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD) \
     : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
  
+ #define ALTIVEC_VECTOR_MODE(MODE)	\
+ 	((MODE) == V16QImode		\
+ 	 || (MODE) == V8HImode		\
+ 	 || (MODE) == V4SFmode		\
+ 	 || (MODE) == V4SImode)
+ 
+ /* Define this macro to be nonzero if the port is prepared to handle
+    insns involving vector mode MODE.  At the very least, it must have
+    move patterns for this mode.  */
+ 
+ #define VECTOR_MODE_SUPPORTED_P(MODE)	\
+ 	(TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (MODE))
+ 
  /* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
     For POWER and PowerPC, the GPRs can hold any mode, but the float
     registers only can hold floating modes and DImode, and CR register only
*************** extern int rs6000_debug_arg;		/* debug a
*** 757,762 ****
--- 832,838 ----
     (GET_MODE_CLASS (MODE) == MODE_FLOAT					\
      || (GET_MODE_CLASS (MODE) == MODE_INT				\
  	&& GET_MODE_SIZE (MODE) == UNITS_PER_FP_WORD))			\
+    : ALTIVEC_REGNO_P (REGNO) ? ALTIVEC_VECTOR_MODE (MODE)		\
     : CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC		\
     : XER_REGNO_P (REGNO) ? (MODE) == PSImode				\
     : ! INT_REGNO_P (REGNO) ? (GET_MODE_CLASS (MODE) == MODE_INT		\
*************** extern int rs6000_debug_arg;		/* debug a
*** 776,781 ****
--- 852,861 ----
     ? 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
*** 785,793 ****
     registers is expensive.  */
  
  #define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2)		\
!    ((CLASS1) == FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 2		\
     : (CLASS1) == FLOAT_REGS && (CLASS2) != FLOAT_REGS ? 10	\
     : (CLASS1) != FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 10	\
     : (((CLASS1) == SPECIAL_REGS || (CLASS1) == MQ_REGS		\
         || (CLASS1) == LINK_REGS || (CLASS1) == CTR_REGS		\
         || (CLASS1) == LINK_OR_CTR_REGS)				\
--- 865,875 ----
     registers is expensive.  */
  
  #define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2)		\
!    ((CLASS1) == FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 2	\
     : (CLASS1) == FLOAT_REGS && (CLASS2) != FLOAT_REGS ? 10	\
     : (CLASS1) != FLOAT_REGS && (CLASS2) == FLOAT_REGS ? 10	\
+    : (CLASS1) == ALTIVEC_REGS && (CLASS2) != ALTIVEC_REGS ? 20	\
+    : (CLASS1) != ALTIVEC_REGS && (CLASS2) == ALTIVEC_REGS ? 20	\
     : (((CLASS1) == SPECIAL_REGS || (CLASS1) == MQ_REGS		\
         || (CLASS1) == LINK_REGS || (CLASS1) == CTR_REGS		\
         || (CLASS1) == LINK_OR_CTR_REGS)				\
*************** extern int rs6000_debug_arg;		/* debug a
*** 839,844 ****
--- 921,932 ----
      global_regs[PIC_OFFSET_TABLE_REGNUM]				\
        = fixed_regs[PIC_OFFSET_TABLE_REGNUM]				\
          = call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;			\
+   if (TARGET_ALTIVEC_ABI)						\
+     {									\
+       fixed_regs[VRSAVE_REGNO] = call_used_regs[VRSAVE_REGNO] = 1;	\
+       for (i = FIRST_ALTIVEC_REGNO; i < FIRST_ALTIVEC_REGNO + 20; ++i)	\
+         call_used_regs[i] = 1;						\
+     }									\
  }
  
  /* Specify the registers used for certain standard purposes.
*************** enum reg_class
*** 912,917 ****
--- 1000,1007 ----
    BASE_REGS,
    GENERAL_REGS,
    FLOAT_REGS,
+   ALTIVEC_REGS,
+   VRSAVE_REGS,
    NON_SPECIAL_REGS,
    MQ_REGS,
    LINK_REGS,
*************** enum reg_class
*** 937,942 ****
--- 1027,1034 ----
    "BASE_REGS",								\
    "GENERAL_REGS",							\
    "FLOAT_REGS",								\
+   "ALTIVEC_REGS",							\
+   "VRSAVE_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:
--- 1047,1072 ----
     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, 0xffffe000, 0x0001ffff }, /* ALTIVEC_REGS */     \
!   { 0x00000000, 0x00000000, 0x00000000, 0x00020000 }, /* VRSAVE_REGS */	     \
!   { 0xffffffff, 0xffffffff, 0x00000008, 0x00000000 }, /* NON_SPECIAL_REGS */ \
!   { 0x00000000, 0x00000000, 0x00000001, 0x00000000 }, /* MQ_REGS */	     \
!   { 0x00000000, 0x00000000, 0x00000002, 0x00000000 }, /* LINK_REGS */	     \
!   { 0x00000000, 0x00000000, 0x00000004, 0x00000000 }, /* CTR_REGS */	     \
!   { 0x00000000, 0x00000000, 0x00000006, 0x00000000 }, /* LINK_OR_CTR_REGS */ \
!   { 0x00000000, 0x00000000, 0x00000007, 0x00000000 }, /* SPECIAL_REGS */     \
!   { 0xffffffff, 0x00000000, 0x0000000f, 0x00000000 }, /* SPEC_OR_GEN_REGS */ \
!   { 0x00000000, 0x00000000, 0x00000010, 0x00000000 }, /* CR0_REGS */	     \
!   { 0x00000000, 0x00000000, 0x00000ff0, 0x00000000 }, /* CR_REGS */	     \
!   { 0xffffffff, 0x00000000, 0x0000ffff, 0x00000000 }, /* NON_FLOAT_REGS */   \
!   { 0x00000000, 0x00000000, 0x00010000, 0x00000000 }, /* XER_REGS */	     \
!   { 0xffffffff, 0xffffffff, 0xffffffff, 0x0001ffff }  /* ALL_REGS */	     \
  }
  
  /* The same information, inverted:
*************** enum reg_class
*** 984,989 ****
--- 1078,1084 ----
   ((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
*** 991,996 ****
--- 1086,1092 ----
    : (REGNO) == COUNT_REGISTER_REGNUM ? CTR_REGS	\
    : (REGNO) == ARG_POINTER_REGNUM ? BASE_REGS	\
    : (REGNO) == XER_REGNO ? XER_REGS		\
+   : (REGNO) == VRSAVE_REGNO ? VRSAVE_REGS	\
    : NO_REGS)
  
  /* The class value for index registers, and the one for base regs.  */
*************** enum reg_class
*** 1006,1011 ****
--- 1102,1108 ----
     : (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.
--- 1200,1213 ----
  #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.
--- 1394,1411 ----
  		&& 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 ****
--- 1440,1454 ----
  			? FP_ARG_AIX_MAX_REG : FP_ARG_V4_MAX_REG)
  #define FP_ARG_NUM_REG (FP_ARG_MAX_REG - FP_ARG_MIN_REG + 1)
  
+ /* Minimum and maximum AltiVec registers used to hold arguments.  */
+ #define ALTIVEC_ARG_MIN_REG (FIRST_ALTIVEC_REGNO + 2)
+ #define ALTIVEC_ARG_MAX_REG (ALTIVEC_ARG_MIN_REG + 11)
+ #define ALTIVEC_ARG_NUM_REG (ALTIVEC_ARG_MAX_REG - ALTIVEC_ARG_MIN_REG + 1)
+ 
  /* Return registers */
  #define GP_ARG_RETURN GP_ARG_MIN_REG
  #define FP_ARG_RETURN FP_ARG_MIN_REG
+ #define ALTIVEC_ARG_RETURN (FIRST_ALTIVEC_REGNO + 2)
  
  /* Flags for the call/call_value rtl operations set up by function_arg */
  #define CALL_NORMAL		0x00000000	/* no special processing */
*************** typedef struct rs6000_stack {
*** 1352,1364 ****
  /* 1 if N is a possible register number for a function value
     as seen by the caller.
  
!    On RS/6000, this is r3 and fp1.  */
! #define FUNCTION_VALUE_REGNO_P(N)  ((N) == GP_ARG_RETURN || ((N) == FP_ARG_RETURN))
  
  /* 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)))
  
  
--- 1460,1477 ----
  /* 1 if N is a possible register number for a function value
     as seen by the caller.
  
!    On RS/6000, this is r3, fp1, and v2 (for AltiVec).  */
! #define FUNCTION_VALUE_REGNO_P(N)  ((N) == GP_ARG_RETURN	\
! 				    || ((N) == FP_ARG_RETURN)	\
! 				    || (TARGET_ALTIVEC &&	\
! 					(N) == ALTIVEC_ARG_RETURN))
  
  /* 1 if N is a possible register number for function argument passing.
     On RS/6000, these are r3-r10 and fp1-fp13.  */
  #define FUNCTION_ARG_REGNO_P(N)						\
    ((unsigned)(((N) - GP_ARG_MIN_REG) < (unsigned)(GP_ARG_NUM_REG))	\
+    || (TARGET_ALTIVEC &&						\
+        (unsigned)((N) - ALTIVEC_ARG_MIN_REG) < (unsigned)(ALTIVEC_ARG_MAX_REG)) \
     || ((unsigned)((N) - FP_ARG_MIN_REG) < (unsigned)(FP_ARG_NUM_REG)))
  
  
*************** typedef struct rs6000_args
*** 1394,1399 ****
--- 1507,1513 ----
  {
    int words;			/* # words used for passing GP registers */
    int fregno;			/* next available FP register */
+   int vregno;			/* next available AltiVec register */
    int nargs_prototype;		/* # args left in the current prototype */
    int orig_nargs;		/* Original value of nargs_prototype */
    int prototype;		/* Whether a prototype was defined */
*************** typedef struct rs6000_args
*** 1436,1441 ****
--- 1550,1561 ----
     && (CUM).fregno <= FP_ARG_MAX_REG    \
     && TARGET_HARD_FLOAT)
  
+ /* Non-zero if we can use an AltiVec register to pass this arg.  */
+ #define USE_ALTIVEC_FOR_ARG_P(CUM,MODE,TYPE)	\
+   (ALTIVEC_VECTOR_MODE (MODE)			\
+    && (CUM).vregno <= ALTIVEC_ARG_MAX_REG	\
+    && TARGET_ALTIVEC_ABI)
+ 
  /* Determine where to put an argument to a function.
     Value is zero to push the argument on the stack,
     or a hard register in which to store the argument.
*************** typedef struct rs6000_args
*** 1778,1783 ****
--- 1898,1904 ----
    && GET_CODE (XEXP (X, 0)) == REG				\
    && INT_REG_OK_FOR_BASE_P (XEXP (X, 0), (STRICT))		\
    && LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 0)		\
+   && (! ALTIVEC_VECTOR_MODE (MODE) || INTVAL (X) == 0)		\
    && (((MODE) != DFmode && (MODE) != DImode)			\
        || (TARGET_32BIT						\
  	  ? LEGITIMATE_ADDRESS_INTEGER_P (XEXP (X, 1), 4) 	\
*************** typedef struct rs6000_args
*** 1805,1810 ****
--- 1926,1932 ----
     && ! flag_pic && ! TARGET_TOC				\
     && (MODE) != DImode						\
     && (MODE) != TImode						\
+    && ! ALTIVEC_VECTOR_MODE (MODE)				\
     && (TARGET_HARD_FLOAT || (MODE) != DFmode)			\
     && GET_CODE (X) == LO_SUM					\
     && GET_CODE (XEXP (X, 0)) == REG				\
*************** extern char rs6000_reg_names[][8];	/* re
*** 2389,2394 ****
--- 2511,2549 ----
    &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.  */
--- 2562,2572 ----
      "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 ****
--- 2588,2601 ----
    {"fr20", 52}, {"fr21", 53}, {"fr22", 54}, {"fr23", 55},	\
    {"fr24", 56}, {"fr25", 57}, {"fr26", 58}, {"fr27", 59},	\
    {"fr28", 60}, {"fr29", 61}, {"fr30", 62}, {"fr31", 63},	\
+   {"v0",   77}, {"v1",   78}, {"v2",   79}, {"v3",   80},       \
+   {"v4",   81}, {"v5",   82}, {"v6",   83}, {"v7",   84},       \
+   {"v8",   85}, {"v9",   86}, {"v10",  87}, {"v11",  88},       \
+   {"v12",  89}, {"v13",  90}, {"v14",  91}, {"v15",  92},       \
+   {"v16",  93}, {"v17",  94}, {"v18",  95}, {"v19",  96},       \
+   {"v20",  97}, {"v21",  98}, {"v22",  99}, {"v23",  100},	\
+   {"v24",  101},{"v25",  102},{"v26",  103},{"v27",  104},      \
+   {"v28",  105},{"v29",  106},{"v30",  107},{"v31",  108},      \
    /* no additional names for: mq, lr, ctr, ap */		\
    {"cr0",  68}, {"cr1",  69}, {"cr2",  70}, {"cr3",  71},	\
    {"cr4",  72}, {"cr5",  73}, {"cr6",  74}, {"cr7",  75},	\
*************** extern int flag_pic;
*** 2629,2631 ****
--- 2796,2911 ----
  extern int optimize;
  extern int flag_expensive_optimizations;
  extern int frame_pointer_needed;
+ 
+ enum rs6000_builtins
+ {
+   /* AltiVec builtins.  */
+   ALTIVEC_BUILTIN_ST_INTERNAL,

*builtins deleted*

+ };
Index: sysv4.h
===================================================================
RCS file: /cvs/uberbaum/gcc/config/rs6000/sysv4.h,v
retrieving revision 1.67
diff -c -p -r1.67 sysv4.h
*** sysv4.h	2001/10/29 23:09:43	1.67
--- sysv4.h	2001/11/06 22:24:42
*************** do {									\
*** 400,417 ****
     one set of libraries with -mno-eabi instead of eabi libraries and non-eabi
     versions, just use 64 as the stack boundary.  */
  #undef	STACK_BOUNDARY
! #define	STACK_BOUNDARY	64
  
  /* Real stack boundary as mandated by the appropriate ABI.  */
! #define ABI_STACK_BOUNDARY ((TARGET_EABI) ? 64 : 128)
  
  /* No data type wants to be aligned rounder than this.  */
  #undef	BIGGEST_ALIGNMENT
! #define BIGGEST_ALIGNMENT ((TARGET_EABI) ? 64 : 128)
  
  #undef  BIGGEST_FIELD_ALIGNMENT
  #undef  ADJUST_FIELD_ALIGN
- #undef  ROUND_TYPE_ALIGN
  
  /* Use ELF style section commands.  */
  
--- 400,430 ----
     one set of libraries with -mno-eabi instead of eabi libraries and non-eabi
     versions, just use 64 as the stack boundary.  */
  #undef	STACK_BOUNDARY
! #define	STACK_BOUNDARY	(TARGET_ALTIVEC_ABI ? 128 : 64)
  
  /* Real stack boundary as mandated by the appropriate ABI.  */
! #define ABI_STACK_BOUNDARY ((TARGET_EABI && !TARGET_ALTIVEC_ABI) ? 64 : 128)
  
  /* No data type wants to be aligned rounder than this.  */
  #undef	BIGGEST_ALIGNMENT
! #define BIGGEST_ALIGNMENT (TARGET_EABI ? 64 : 128)
  
+ /* An expression for the alignment of a structure field FIELD if the
+    alignment computed in the usual way is COMPUTED.  */
+ #define ADJUST_FIELD_ALIGN(FIELD, COMPUTED)				      \
+ 	((TARGET_ALTIVEC && TREE_CODE (TREE_TYPE (FIELD)) == VECTOR_TYPE)     \
+ 	 ? 128 : COMPUTED)
+ 
+ /* Define this macro as an expression for the alignment of a type
+    (given by TYPE as a tree node) if the alignment computed in the
+    usual way is COMPUTED and the alignment explicitly specified was
+    SPECIFIED.  */
+ #define ROUND_TYPE_ALIGN(TYPE, COMPUTED, SPECIFIED)			\
+ 	((TARGET_ALTIVEC  && TREE_CODE (TYPE) == VECTOR_TYPE)	        \
+ 	 ? 128 : MAX (COMPUTED, SPECIFIED))
+ 
  #undef  BIGGEST_FIELD_ALIGNMENT
  #undef  ADJUST_FIELD_ALIGN
  
  /* Use ELF style section commands.  */
  
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/11/06 22:24:45
*************** int fixuplabelno = 0;
*** 96,101 ****
--- 96,104 ----
  /* ABI enumeration available for subtarget to use.  */
  enum rs6000_abi rs6000_current_abi;
  
+ /* ABI string from -mabi= option.  */
+ const char *rs6000_abi_string;
+ 
  /* Debug flags */
  const char *rs6000_debug_name;
  int rs6000_debug_stack;		/* debug stack applications */
*************** static int rs6000_adjust_cost PARAMS ((r
*** 146,151 ****
--- 149,161 ----
  static int rs6000_adjust_priority PARAMS ((rtx, int));
  static int rs6000_issue_rate PARAMS ((void));
  
+ static void rs6000_init_builtins PARAMS ((tree));
+ static void altivec_init_builtins PARAMS ((void));
+ static rtx rs6000_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
+ static rtx altivec_expand_builtin PARAMS ((tree, rtx, rtx, enum machine_mode, int));
+ static rtx altivec_expand_binop_builtin PARAMS ((enum insn_code, tree, rtx));
+ 
+ static void rs6000_parse_abi_options PARAMS ((void));
  
  /* Default register names.  */
  char rs6000_reg_names[][8] =
*************** 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
--- 170,181 ----
       "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
  
--- 191,202 ----
    "%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 ****
--- 225,236 ----
  #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
*************** rs6000_override_options (default_cpu)
*** 438,443 ****
--- 464,472 ----
  	error ("Unknown -mdebug-%s switch", rs6000_debug_name);
      }
  
+   /* Handle -mabi= options.  */
+   rs6000_parse_abi_options ();
+ 
  #ifdef TARGET_REGNAMES
    /* If the user desires alternate register names, copy in the
       alternate names now.  */
*************** rs6000_override_options (default_cpu)
*** 463,468 ****
--- 492,508 ----
    free_machine_status = rs6000_free_machine_status;
  }
  
+ /* Handle -mabi= options.  */
+ void rs6000_parse_abi_options ()
+ {
+   if (rs6000_abi_string == 0)
+     return;
+   else if (! strcmp (rs6000_abi_string, "altivec"))
+     target_flags |= MASK_ALTIVEC_ABI;
+   else
+     error ("Unknown ABI specified: '%s'", rs6000_abi_string);
+ }
+ 
  void
  optimization_options (level, size)
       int level ATTRIBUTE_UNUSED;
*************** 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
--- 1584,1590 ----
       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 ****
--- 1610,1627 ----
        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 ****
--- 1914,1928 ----
  	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 */
*************** init_cumulative_args (cum, fntype, libna
*** 2062,2067 ****
--- 2123,2129 ----
    *cum = zero_cumulative;
    cum->words = 0;
    cum->fregno = FP_ARG_MIN_REG;
+   cum->vregno = ALTIVEC_ARG_MIN_REG;
    cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
    cum->call_cookie = CALL_NORMAL;
    cum->sysv_gregno = GP_ARG_MIN_REG;
*************** function_arg_boundary (mode, type)
*** 2142,2147 ****
--- 2204,2211 ----
    if ((DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
        && (mode == DImode || mode == DFmode))
      return 64;
+   else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+     return 128;
    else
      return PARM_BOUNDARY;
  }
*************** function_arg_advance (cum, mode, type, n
*** 2159,2165 ****
  {
    cum->nargs_prototype--;
  
!   if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
      {
        if (TARGET_HARD_FLOAT
  	  && (mode == SFmode || mode == DFmode))
--- 2223,2236 ----
  {
    cum->nargs_prototype--;
  
!   if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
!     {
!       if (cum->vregno <= ALTIVEC_ARG_MAX_REG && cum->nargs_prototype >= 0)
! 	cum->vregno++;
!       else
! 	cum->words += RS6000_ARG_SIZE (mode, type);
!     }
!   else if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
      {
        if (TARGET_HARD_FLOAT
  	  && (mode == SFmode || mode == DFmode))
*************** function_arg (cum, mode, type, named)
*** 2287,2293 ****
        return GEN_INT (cum->call_cookie);
      }
  
!   if (abi == ABI_V4 || abi == ABI_SOLARIS)
      {
        if (TARGET_HARD_FLOAT
  	  && (mode == SFmode || mode == DFmode))
--- 2358,2371 ----
        return GEN_INT (cum->call_cookie);
      }
  
!   if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
!     {
!       if (cum->vregno <= ALTIVEC_ARG_MAX_REG)
! 	return gen_rtx_REG (mode, cum->vregno);
!       else
! 	return NULL;
!     }
!   else if (abi == ABI_V4 || abi == ABI_SOLARIS)
      {
        if (TARGET_HARD_FLOAT
  	  && (mode == SFmode || mode == DFmode))
*************** function_arg_partial_nregs (cum, mode, t
*** 2382,2388 ****
    if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
      return 0;
  
!   if (USE_FP_FOR_ARG_P (*cum, mode, type))
      {
        if (cum->nargs_prototype >= 0)
  	return 0;
--- 2460,2467 ----
    if (DEFAULT_ABI == ABI_V4 || DEFAULT_ABI == ABI_SOLARIS)
      return 0;
  
!   if (USE_FP_FOR_ARG_P (*cum, mode, type)
!       || USE_ALTIVEC_FOR_ARG_P (*cum, mode, type))
      {
        if (cum->nargs_prototype >= 0)
  	return 0;
*************** rs6000_va_arg (valist, type)
*** 2838,2843 ****
--- 2917,3392 ----
  
    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 },

*builtins deleted*

+ };
+ 
+ static rtx
+ altivec_expand_binop_builtin (icode, arglist, target)
+      enum insn_code icode;
+      tree arglist;
+      rtx target;
+ {
+   rtx pat;
+   tree arg0 = TREE_VALUE (arglist);
+   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+   rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+   rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+   enum machine_mode tmode = insn_data[icode].operand[0].mode;
+   enum machine_mode mode0 = insn_data[icode].operand[1].mode;
+   enum machine_mode mode1 = insn_data[icode].operand[2].mode;
+ 
+   if (! target
+       || GET_MODE (target) != tmode
+       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+     target = gen_reg_rtx (tmode);
+ 
+   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+     op0 = copy_to_mode_reg (mode0, op0);
+   if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
+     op1 = copy_to_mode_reg (mode1, op1);
+ 
+   pat = GEN_FCN (icode) (target, op0, op1);
+   if (! pat)
+     return 0;
+   emit_insn (pat);
+ 
+   return target;
+ }
+ 
+ static rtx
+ altivec_expand_builtin (exp, target, subtarget, mode, ignore)
+      tree exp;
+      rtx target;
+      rtx subtarget;
+      enum machine_mode mode;
+      int ignore;
+ {
+   struct builtin_description *d;
+   size_t i;
+   enum insn_code icode;
+   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+   tree arglist = TREE_OPERAND (exp, 1);
+   tree arg0, arg1, arg2, arg3;
+   rtx op0, op1, op2, pat;
+   enum machine_mode tmode, mode0, mode1, mode2;
+   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+   
+   switch (fcode)
+     {
+     case ALTIVEC_BUILTIN_LD_INTERNAL:
+       icode = CODE_FOR_altivec_lvx;
+       arg0 = TREE_VALUE (arglist);
+       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+       tmode = insn_data[icode].operand[0].mode;
+       mode0 = insn_data[icode].operand[1].mode;
+ 
+       if (! target
+ 	  || GET_MODE (target) != tmode
+ 	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+ 	target = gen_reg_rtx (tmode);
+ 
+       if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
+ 	op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
+ 
+       pat = GEN_FCN (icode) (target, op0);
+       if (! pat)
+ 	return 0;
+       emit_insn (pat);
+       return target;
+ 
+     case ALTIVEC_BUILTIN_ST_INTERNAL:
+       icode = CODE_FOR_altivec_stvx;
+       arg0 = TREE_VALUE (arglist);
+       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+       op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+       mode0 = insn_data[icode].operand[0].mode;
+       mode1 = insn_data[icode].operand[1].mode;
+ 
+       if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
+ 	op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
+       if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
+ 	op1 = copy_to_mode_reg (mode1, op1);
+ 
+       pat = GEN_FCN (icode) (op0, op1);
+       if (! pat)
+ 	return 0;
+       emit_insn (pat);
+       return NULL_RTX;
+     }
+ 
+   /* Handle simple binary operations.  */
+   for (i = 0, d = bdesc_2arg; i < sizeof (bdesc_2arg) / sizeof *d; i++, d++)
+     if (d->code == fcode)
+       return altivec_expand_binop_builtin (d->icode, arglist, target);
+ 
+   abort ();
+   return NULL_RTX;
+ }
+ 
+ /* Expand an expression EXP that calls a built-in function,
+    with result going to TARGET if that's convenient
+    (and in mode MODE if that's convenient).
+    SUBTARGET may be used as the target for computing one of EXP's operands.
+    IGNORE is nonzero if the value is to be ignored.  */
+ 
+ static rtx
+ rs6000_expand_builtin (exp, target, subtarget, mode, ignore)
+      tree exp;
+      rtx target;
+      rtx subtarget;
+      enum machine_mode mode;
+      int ignore;
+ {
+   if (TARGET_ALTIVEC)
+     return altivec_expand_builtin (exp, target, subtarget, mode, ignore);
+ 
+   abort ();
+ }
+ 
+ static void
+ rs6000_init_builtins (list_node)
+      tree list_node ATTRIBUTE_UNUSED;
+ {
+   if (TARGET_ALTIVEC)
+     altivec_init_builtins ();
+ }
+ 
+ static void
+ altivec_init_builtins (void)
+ {
+   struct builtin_description * d;
+   size_t i;
+ 
+   tree endlink = void_list_node;
+ 
+   tree pint_type_node = build_pointer_type (integer_type_node);
+ 
+   /* V4SI foo (int *).  */
+   tree v4si_ftype_pint
+     = build_function_type (V4SI_type_node,
+ 			   tree_cons (NULL_TREE, pint_type_node, endlink));
+ 
+   /* void foo (int *, V4SI).  */
+   tree void_ftype_pint_v4si
+     = build_function_type (void_type_node,
+ 			   tree_cons (NULL_TREE, pint_type_node,
+ 				      tree_cons (NULL_TREE, V4SI_type_node,
+ 						 endlink)));
+ 
+   tree v4si_ftype_v4si_v4si
+     = build_function_type (V4SI_type_node,
+ 			   tree_cons (NULL_TREE, V4SI_type_node,
+ 				      tree_cons (NULL_TREE, V4SI_type_node,
+ 						 endlink)));
+ 
+   tree v4sf_ftype_v4sf_v4sf
+     = build_function_type (V4SF_type_node,
+ 			   tree_cons (NULL_TREE, V4SF_type_node,
+ 				      tree_cons (NULL_TREE, V4SF_type_node,
+ 						 endlink)));
+ 
+   tree v8hi_ftype_v8hi_v8hi
+     = build_function_type (V8HI_type_node,
+ 			   tree_cons (NULL_TREE, V8HI_type_node,
+ 				      tree_cons (NULL_TREE, V8HI_type_node,
+ 						 endlink)));
+ 
+   tree v16qi_ftype_v16qi_v16qi
+     = build_function_type (V16QI_type_node,
+ 			   tree_cons (NULL_TREE, V16QI_type_node,
+ 				      tree_cons (NULL_TREE, V16QI_type_node,
+ 						 endlink)));
+ 
+   tree v4si_ftype_v4sf_v4sf
+     = build_function_type (V4SI_type_node,
+ 			   tree_cons (NULL_TREE, V4SF_type_node,
+ 				      tree_cons (NULL_TREE, V4SF_type_node,
+ 						 endlink)));
+ 
+   tree v8hi_ftype_v16qi_v16qi
+     = build_function_type (V8HI_type_node,
+ 			   tree_cons (NULL_TREE, V16QI_type_node,
+ 				      tree_cons (NULL_TREE, V16QI_type_node,
+ 						 endlink)));
+ 
+   tree v4si_ftype_v8hi_v8hi
+     = build_function_type (V4SI_type_node,
+ 			   tree_cons (NULL_TREE, V8HI_type_node,
+ 				      tree_cons (NULL_TREE, V8HI_type_node,
+ 						 endlink)));
+ 
+   tree v8hi_ftype_v4si_v4si
+     = build_function_type (V8HI_type_node,
+ 			   tree_cons (NULL_TREE, V4SI_type_node,
+ 				      tree_cons (NULL_TREE, V4SI_type_node,
+ 						 endlink)));
+ 
+   tree v16qi_ftype_v8hi_v8hi
+     = build_function_type (V16QI_type_node,
+ 			   tree_cons (NULL_TREE, V8HI_type_node,
+ 				      tree_cons (NULL_TREE, V8HI_type_node,
+ 						 endlink)));
+ 
+   tree v4si_ftype_v16qi_v4si
+     = build_function_type (V4SI_type_node,
+ 			   tree_cons (NULL_TREE, V16QI_type_node,
+ 				      tree_cons (NULL_TREE, V4SI_type_node,
+ 						 endlink)));
+ 
+   tree v4si_ftype_v8hi_v4si
+     = build_function_type (V4SI_type_node,
+ 			   tree_cons (NULL_TREE, V8HI_type_node,
+ 				      tree_cons (NULL_TREE, V4SI_type_node,
+ 						 endlink)));
+ 
+   tree int_ftype_v4si_v4si
+     = build_function_type (integer_type_node,
+ 			   tree_cons (NULL_TREE, V4SI_type_node,
+ 				      tree_cons (NULL_TREE, V4SI_type_node,
+ 						 endlink)));
+ 
+   tree int_ftype_v4sf_v4sf
+     = build_function_type (integer_type_node,
+ 			   tree_cons (NULL_TREE, V4SF_type_node,
+ 				      tree_cons (NULL_TREE, V4SF_type_node,
+ 						 endlink)));
+ 
+   tree int_ftype_v16qi_v16qi
+     = build_function_type (integer_type_node,
+ 			   tree_cons (NULL_TREE, V16QI_type_node,
+ 				      tree_cons (NULL_TREE, V16QI_type_node,
+ 						 endlink)));
+ 
+   tree int_ftype_v8hi_v8hi
+     = build_function_type (integer_type_node,
+ 			   tree_cons (NULL_TREE, V8HI_type_node,
+ 				      tree_cons (NULL_TREE, V8HI_type_node,
+ 						 endlink)));
+ 
+   def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal", v4si_ftype_pint, ALTIVEC_BUILTIN_LD_INTERNAL);
+   def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal", void_ftype_pint_v4si, ALTIVEC_BUILTIN_ST_INTERNAL);
+ 
+   /* Add the simple binary operators.  */
+   for (i = 0, d = bdesc_2arg; i < sizeof (bdesc_2arg) / sizeof *d; i++, d++)
+     {
+       enum machine_mode mode0, mode1, mode2;
+       tree type;
+ 
+       if (d->name == 0)
+ 	continue;
+       
+       mode0 = insn_data[d->icode].operand[0].mode;
+       mode1 = insn_data[d->icode].operand[1].mode;
+       mode2 = insn_data[d->icode].operand[2].mode;
+ 
+       /* When all three operands are of the same mode.  */
+       if (mode0 == mode1 && mode1 == mode2)
+ 	{
+ 	  switch (mode0)
+ 	    {
+ 	    case V4SFmode:
+ 	      type = v4sf_ftype_v4sf_v4sf;
+ 	      break;
+ 	    case V4SImode:
+ 	      type = v4si_ftype_v4si_v4si;
+ 	      break;
+ 	    case V16QImode:
+ 	      type = v16qi_ftype_v16qi_v16qi;
+ 	      break;
+ 	    case V8HImode:
+ 	      type = v8hi_ftype_v8hi_v8hi;
+ 	      break;
+ 	    default:
+ 	      abort ();
+ 	    }
+ 	}
+ 
+       /* A few other combos we really don't want to do manually.  */
+ 
+       /* vint, vfloat, vfloat.  */
+       else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == V4SFmode)
+ 	type = v4si_ftype_v4sf_v4sf;
+ 
+       /* vshort, vchar, vchar.  */
+       else if (mode0 == V8HImode && mode1 == V16QImode && mode2 == V16QImode)
+ 	type = v8hi_ftype_v16qi_v16qi;
+ 
+       /* vint, vshort, vshort.  */
+       else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode)
+ 	type = v4si_ftype_v8hi_v8hi;
+ 
+       /* vshort, vint, vint.  */
+       else if (mode0 == V8HImode && mode1 == V4SImode && mode2 == V4SImode)
+ 	type = v8hi_ftype_v4si_v4si;
+ 
+       /* vchar, vshort, vshort.  */
+       else if (mode0 == V16QImode && mode1 == V8HImode && mode2 == V8HImode)
+ 	type = v16qi_ftype_v8hi_v8hi;
+ 
+       /* vint, vchar, vint.  */
+       else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V4SImode)
+ 	type = v4si_ftype_v16qi_v4si;
+ 
+       /* vint, vshort, vint.  */
+       else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V4SImode)
+ 	type = v4si_ftype_v8hi_v4si;
+ 
+       /* fixme: aldyh */
+       /* int, x, x.  */
+       else if (mode0 == SImode)
+ 	{
+ 	  switch (mode1)
+ 	    {
+ 	    case V4SImode:
+ 	      type = int_ftype_v4si_v4si;
+ 	      break;
+ 	    case V4SFmode:
+ 	      type = int_ftype_v4sf_v4sf;
+ 	      break;
+ 	    case V16QImode:
+ 	      type = int_ftype_v16qi_v16qi;
+ 	      break;
+ 	    case V8HImode:
+ 	      type = int_ftype_v8hi_v8hi;
+ 	      break;
+ 	    default:
+ 	      abort ();
+ 	    }
+ 	}
+ 
+       else
+ 	abort ();
+ 
+       def_builtin (d->mask, d->name, type, d->code);
+     }
+ }
+ 
  
  /* Generate a memory reference for expand_block_move, copying volatile,
     and other bits from an original memory reference.  */
*************** secondary_reload_class (class, mode, in)
*** 3941,3946 ****
--- 4490,4500 ----
        && (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 ****
--- 5268,5299 ----
  		     reg_names[SMALL_DATA_REG]);
  	}
        return;
+ 
+       /* Print AltiVec memory operand.  */
+     case 'y':
+       {
+ 	rtx tmp;
+ 
+ 	if (GET_CODE (x) != MEM)
+ 	  abort ();
+ 
+ 	tmp = XEXP (x, 0);
+ 
+ 	if (GET_CODE (tmp) == REG)
+ 	  fprintf (file, "0, %s", reg_names[REGNO (tmp)]);
+ 	else if (GET_CODE (tmp) == PLUS && GET_CODE (XEXP (tmp, 1)) == REG)
+ 	  {
+ 	    if (REGNO (XEXP (tmp, 0)) == 0)
+ 	      fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (tmp, 1)) ],
+ 		       reg_names[ REGNO (XEXP (tmp, 0)) ]);
+ 	    else
+ 	      fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (tmp, 0)) ],
+ 		       reg_names[ REGNO (XEXP (tmp, 1)) ]);
+ 	  }
+ 	else
+ 	  abort ();
+ 	break;
+       }
  			    
      case 0:
        if (GET_CODE (x) == REG)
Index: 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/11/06 22:24:51
***************
*** 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,14294 ----
      emit_move_insn (gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM), operands[0]);
    DONE;
  }")
+ 
+ ;; AltiVec patterns
+ 
+ ;; Generic LVX load instruction.
+ (define_insn "altivec_lvx"
+   [(set (match_operand:V4SI 0 "register_operand" "=v")
+ 	(match_operand:V4SI 1 "memory_operand" "m"))]
+   "TARGET_ALTIVEC"
+   "lvx\t%0,%y1"
+   [(set_attr "type" "altivec")])
+ 
+ ;; Generic STVX store instruction.
+ (define_insn "altivec_stvx"
+   [(set (match_operand:V4SI 0 "memory_operand" "=m")
+ 	(match_operand:V4SI 1 "register_operand" "v"))]
+   "TARGET_ALTIVEC"
+   "stvx\t%1,%y0"
+   [(set_attr "type" "altivec")])
+ 
+ ;; Vector move instructions.
+ (define_expand "movv4si"
+   [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
+ 	(match_operand:V4SI 1 "any_operand" ""))]
+   "TARGET_ALTIVEC"
+   "{ rs6000_emit_move (operands[0], operands[1], V4SImode); DONE; }")
+ 
+ (define_insn "*movv4si_internal"
+   [(set (match_operand:V4SI 0 "nonimmediate_operand" "=m,v,v")
+ 	(match_operand:V4SI 1 "input_operand" "v,m,v"))]
+   "TARGET_ALTIVEC"
+   "@
+    stvx\t%1,%y0
+    ldvx\t%0,%y1
+    vor\t%0,%1,%1"
+   [(set_attr "type" "altivec")])
+ 
+ (define_expand "movv8hi"
+   [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
+ 	(match_operand:V8HI 1 "any_operand" ""))]
+   "TARGET_ALTIVEC"
+   "{ rs6000_emit_move (operands[0], operands[1], V8HImode); DONE; }")
+ 
+ (define_insn "*movv8hi_internal1"
+   [(set (match_operand:V8HI 0 "nonimmediate_operand" "=m,v,v")
+ 	(match_operand:V8HI 1 "input_operand" "v,m,v"))]
+   "TARGET_ALTIVEC"
+   "@
+    stvx\t%1,%y0
+    ldvx\t%0,%y1
+    vor\t%0,%1,%1"
+   [(set_attr "type" "altivec")])
+ 
+ (define_expand "movv16qi"
+   [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
+ 	(match_operand:V16QI 1 "any_operand" ""))]
+   "TARGET_ALTIVEC"
+   "{ rs6000_emit_move (operands[0], operands[1], V16QImode); DONE; }")
+ 
+ (define_insn "*movv16qi_internal1"
+   [(set (match_operand:V16QI 0 "nonimmediate_operand" "=m,v,v")
+ 	(match_operand:V16QI 1 "input_operand" "v,m,v"))]
+   "TARGET_ALTIVEC"
+   "@
+    stvx\t%1,%y0
+    ldvx\t%0,%y1
+    vor\t%0,%1,%1"
+   [(set_attr "type" "altivec")])
+ 
+ (define_expand "movv4sf"
+   [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
+ 	(match_operand:V4SF 1 "any_operand" ""))]
+   "TARGET_ALTIVEC"
+   "{ rs6000_emit_move (operands[0], operands[1], V4SFmode); DONE; }")
+ 
+ (define_insn "*movv4sf_internal1"
+   [(set (match_operand:V4SF 0 "nonimmediate_operand" "=m,v,v")
+ 	(match_operand:V4SF 1 "input_operand" "v,m,v"))]
+   "TARGET_ALTIVEC"
+   "@
+    stvx\t%1,%y0
+    ldvx\t%0,%y1
+    vor\t%0,%1,%1"
+   [(set_attr "type" "altivec")])
+ 
+ ;; Simple binary operations.
+ 
+ (define_insn "altivec_vaddubm"
+   [(set (match_operand:V16QI 0 "register_operand" "=v")
+         (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
+                        (match_operand:V16QI 2 "register_operand" "v")] 31))]
+   "TARGET_ALTIVEC"
+   "vaddubm\t%0,%1,%2"
+   [(set_attr "type" "altivec")])

*builtins deleted*


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