public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* altivec patches
@ 2001-11-05 12:52 Aldy Hernandez
  2001-11-05 12:58 ` Aldy Hernandez
                   ` (6 more replies)
  0 siblings, 7 replies; 185+ messages in thread
From: Aldy Hernandez @ 2001-11-05 12:52 UTC (permalink / raw)
  To: gcc patches; +Cc: Geoff Keating

finally...

i have fixed everything that was commented on.
alignment macros are in place, a new abi extension (TARGET_ALTIVEC_ABI),
documentation, etc. 

i have not documented the builtins because i'm going to write a script
to generate those automagially later.  besides, there's pretty much a
1:1 correspondence between the altivec insns and the builtin names 

i have added an option "-mabi=altivec" that enhances the current abi
with altivec ABI extensions.  this flag does NOT replace the current
abi, but extends the current abi to handle altivec extensions as
documented by the motorola manuals. 

i have promised geoff i will rewrite the -mcall-foo hackery and
implement "-mabi=sysv,eabi,altivec" style abi flags.  i will do this
after i'm done with the altivec stuff.  i don't want to diverge the
purpose of this patch into unrelated abi functionality.  right now
-mabi= only supports -mabi=altivec. 
what is left?
    - the rest of the gazillion builtins
    
    - varargs
    
    - frame stuff: epilogue, prologue, vrsave
    - <altivec.h> for the user.  this .h will implement the overloaded
    altivec functions described in the "altivec programming interface
    model".  Stuff like generic (overloaded) "vec_add(veca, vecb)". 
    
    - test cases.  i will commit a few simple tests, but serious tests
    will come after i'm done playing with the G3 box. 
    
and then there's the front end changes, but that's a different story. 

i have tested this on powerpc-unknown-linux-gnu.  it bootstraps.  no
regressions on testsuite. 

the patch below has the boring builtin stuff deleted (as requested). 
there's just 1 or 2 builtins for proof of concept. 

ok to install? 
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.
	(PREDICATE_CODES): Add altivec_register.
	(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.
	
	* 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.
	(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.
	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.
	(*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.

--builtins changelog removed--
	
	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/05 19:49:18
*************** 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/05 19:49:23
*************** 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 (TARGET_ALTIVEC_ABI ? 128 : 64)
! 
! /* 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_ABI		    			\
! 	  && 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,640 ****
     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.  */
--- 659,665 ----
     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.  */
*************** 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
--- 680,690 ----
     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
--- 698,709 ----
     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  \
! }
! 
  
  #define MQ_REGNO     64
  #define CR0_REGNO    68
*************** extern int rs6000_debug_arg;		/* debug a
*** 679,684 ****
--- 713,720 ----
  #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,	\
--- 737,753 ----
  	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)
--- 761,774 ----
     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 ****
--- 785,793 ----
  /* 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 ****
--- 799,821 ----
  #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 ****
--- 827,834 ----
     (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)		\
+    : 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 ****
--- 848,857 ----
     ? 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 ****
--- 864,870 ----
     ((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)				\
*************** extern int rs6000_debug_arg;		/* debug a
*** 839,844 ****
--- 916,924 ----
      global_regs[PIC_OFFSET_TABLE_REGNUM]				\
        = fixed_regs[PIC_OFFSET_TABLE_REGNUM]				\
          = call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;			\
+   if (TARGET_ALTIVEC_ABI)						\
+     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 ****
--- 992,998 ----
    BASE_REGS,
    GENERAL_REGS,
    FLOAT_REGS,
+   ALTIVEC_REGS,
    NON_SPECIAL_REGS,
    MQ_REGS,
    LINK_REGS,
*************** enum reg_class
*** 937,942 ****
--- 1018,1024 ----
    "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:
--- 1037,1061 ----
     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 */     \
!   { 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 ****
--- 1067,1073 ----
   ((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 ****
--- 1090,1096 ----
     : (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.
--- 1188,1201 ----
  #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.
--- 1382,1399 ----
  		&& 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 ****
--- 1428,1442 ----
  			? 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 88
+ #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 {
*** 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)))
  
  \f
--- 1448,1465 ----
  /* 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)))
  
  \f
*************** typedef struct rs6000_args
*** 1394,1399 ****
--- 1495,1501 ----
  {
    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 ****
--- 1538,1549 ----
     && (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 ****
--- 1886,1892 ----
    && 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 ****
--- 1914,1920 ----
     && ! 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 ****
--- 2499,2537 ----
    &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.  */
--- 2550,2560 ----
      "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 ****
--- 2576,2589 ----
    {"fr20", 52}, {"fr21", 53}, {"fr22", 54}, {"fr23", 55},	\
    {"fr24", 56}, {"fr25", 57}, {"fr26", 58}, {"fr27", 59},	\
    {"fr28", 60}, {"fr29", 61}, {"fr30", 62}, {"fr31", 63},	\
+   {"v0",   77}, {"v1",   78}, {"v2",   79}, {"v3",   80},       \
+   {"v4",   81}, {"v5",   82}, {"v6",   83}, {"v7",   84},       \
+   {"v8",   85}, {"v9",   86}, {"v10",  87}, {"v11",  88},       \
+   {"v12",  89}, {"v13",  90}, {"v14",  91}, {"v15",  92},       \
+   {"v16",  93}, {"v17",  94}, {"v18",  95}, {"v19",  96},       \
+   {"v20",  97}, {"v21",  98}, {"v22",  99}, {"v23",  100},	\
+   {"v24",  101},{"v25",  102},{"v26",  103},{"v27",  104},      \
+   {"v28",  105},{"v29",  106},{"v30",  107},{"v31",  108},      \
    /* no additional names for: mq, lr, ctr, ap */		\
    {"cr0",  68}, {"cr1",  69}, {"cr2",  70}, {"cr3",  71},	\
    {"cr4",  72}, {"cr5",  73}, {"cr6",  74}, {"cr7",  75},	\
*************** do {									\
*** 2617,2622 ****
--- 2772,2778 ----
  				GT, LEU, LTU, GEU, GTU}},		   \
    {"boolean_operator", {AND, IOR, XOR}},				   \
    {"boolean_or_operator", {IOR, XOR}},					   \
+   {"altivec_register", {REG, SUBREG}},					   \
    {"min_max_operator", {SMIN, SMAX, UMIN, UMAX}},
  
  /* uncomment for disabling the corresponding default options */
*************** extern int flag_pic;
*** 2629,2631 ****
--- 2785,2900 ----
  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,

--more boring 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/05 19:49:24
*************** 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 && !TARGET_ALTIVEC_ABI) ? 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_ABI && 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_ABI && 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/05 19:49:27
*************** 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));
  \f
  /* 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
  \f
--- 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
  \f
*************** 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;
  \f
  /* 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;
*************** input_operand (op, mode)
*** 1411,1416 ****
--- 1451,1475 ----
    return 0;
  }
  
+ /* Return 1 if this is an AltiVec vector register.
+ 
+    Actually, what we really want to know is if this is a vector mode,
+    since vectors can only go in AltiVec registers.
+ 
+    This is used in *altivec_vec_move so we can seamlessly convert
+    between vector types.  */
+ 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
--- 1603,1609 ----
       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 ****
--- 1629,1646 ----
        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 ****
--- 1933,1947 ----
  	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 ****
--- 2142,2148 ----
    *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 ****
--- 2223,2230 ----
    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))
--- 2242,2255 ----
  {
    cum->nargs_prototype--;
  
!   if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
!     {
!       if (cum->vregno <= ALTIVEC_ARG_MAX_REG)
! 	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,2294 ****
        return GEN_INT (cum->call_cookie);
      }
  
!   if (abi == ABI_V4 || abi == ABI_SOLARIS)
      {
        if (TARGET_HARD_FLOAT
  	  && (mode == SFmode || mode == DFmode))
  	{
--- 2377,2391 ----
        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;
--- 2479,2486 ----
    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 ****
--- 2936,3411 ----
  
    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 },

--more boring 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)));
+ 

--more boring types deleted--

+ 
+   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);
+     }
+ }
+ 
  \f
  /* 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 ****
--- 4509,4519 ----
        && (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 ****
--- 5287,5318 ----
  		     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/05 19:49:32
***************
*** 37,43 ****
  \f
  ;; 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 ----
  \f
  ;; 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,14298 ----
      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.
+ 

-- boring builtins deleted-- 

+ (define_insn "altivec_vxor"
+   [(set (match_operand:V4SI 0 "register_operand" "=v")
+         (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+                       (match_operand:V4SI 2 "register_operand" "v")] 136))]
+   "TARGET_ALTIVEC"
+   "vxor\t%0,%1,%2"
+   [(set_attr "type" "altivec")])

^ permalink raw reply	[flat|nested] 185+ messages in thread
* Re: altivec patches
@ 2001-11-07 10:02 David Edelsohn
  2001-11-07 10:09 ` Aldy Hernandez
                   ` (3 more replies)
  0 siblings, 4 replies; 185+ messages in thread
From: David Edelsohn @ 2001-11-07 10:02 UTC (permalink / raw)
  To: aldyh; +Cc: gcc-patches

	I do not understand what the current proposal for
BIGGEST_ALIGNMENT is.  Are you proposing making it 128 all the time or ack
to selecting the ABI?

	I don't disagree with making BIGGEST_ALIGNMENT 128, but some AIX
and Darwin macros use BIGGEST_ALIGNMENT and expect it to be 64.  If you
change BIGGEST_ALIGNMENT, the other macros in rs6000 directory need to use
64 or some other symbolic name for 64.

David

^ permalink raw reply	[flat|nested] 185+ messages in thread
* Re: altivec patches
@ 2001-11-08 14:33 David Edelsohn
  2001-11-13  5:26 ` David Edelsohn
  2001-11-13 15:03 ` David Edelsohn
  0 siblings, 2 replies; 185+ messages in thread
From: David Edelsohn @ 2001-11-08 14:33 UTC (permalink / raw)
  To: Aldy Hernandez; +Cc: gcc-patches

	I now am getting bootstrap errors on the mainline related to
Altivec infrastructure:

/gcc/dje/src/gcc/libgcc2.c:147: Insn does not satisfy its constraints:
(insn 112 14 115 (set (reg:SI 109 vrsave [119])
        (reg:SI 0 r0)) 289 {*movsi_internal1} (nil)
    (nil))
/gcc/dje/src/gcc/libgcc2.c:147: Internal compiler error in reload_cse_simplify_o
perands, at reload1.c:8340
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL: http://www.gnu.org/software/gcc/bugs.html > for instructions.

	Looking at the rs6000.h patches, I have two questions:

1) Why isn't VRSAVE included in ALL_REGS class?

2) When Altivec is *NOT* enabled, why aren't all of the Altivec registers
and vrsave marked as fixed and call_used?

	Maybe it would be better to define them as 1 in the
FIXED_REGISTERS and CALL_USED_REGISTERS macro and set the appropriate ones
to 0 in CONDITIONAL_REGISTER_USAGE based on options instead of vice-versa.

David

^ permalink raw reply	[flat|nested] 185+ messages in thread

end of thread, other threads:[~2001-11-17 20:54 UTC | newest]

Thread overview: 185+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2001-11-05 12:52 altivec patches Aldy Hernandez
2001-11-05 12:58 ` Aldy Hernandez
2001-11-13  4:32   ` Aldy Hernandez
2001-11-13 15:03   ` Aldy Hernandez
2001-11-05 12:59 ` Joseph S. Myers
2001-11-05 13:04   ` Aldy Hernandez
2001-11-05 13:17     ` Joseph S. Myers
2001-11-13  4:32       ` Joseph S. Myers
2001-11-13 15:03       ` Joseph S. Myers
2001-11-13  4:32     ` Aldy Hernandez
2001-11-13 15:03     ` Aldy Hernandez
2001-11-13  4:32   ` Joseph S. Myers
2001-11-13 15:03   ` Joseph S. Myers
2001-11-05 13:59 ` Geoff Keating
2001-11-05 14:05   ` Alan Matsuoka
2001-11-05 18:22     ` Aldy Hernandez
2001-11-05 18:28       ` Alan Matsuoka
2001-11-05 18:41         ` Include facility for .md files - " Alan Matsuoka
2001-11-03 20:37           ` Geoff Keating
2001-11-13  4:26             ` Geoff Keating
2001-11-13 13:21             ` Geoff Keating
2001-11-13 15:03             ` Aldy Hernandez
2001-11-13 15:03               ` Alan Matsuoka
2001-11-13 15:03               ` Alan Matsuoka
2001-11-13 15:03             ` Geoff Keating
2001-11-05 18:49           ` Joseph S. Myers
2001-11-05 19:03             ` Alan Matsuoka
2001-11-06  1:03               ` Joseph S. Myers
2001-11-06  4:56                 ` Alan Matsuoka
2001-11-06  7:58                   ` Alan Matsuoka
2001-11-13  4:32                     ` Alan Matsuoka
2001-11-13 15:03                     ` Alexandre Oliva
2001-11-13 15:03                       ` Alan Matsuoka
2001-11-13 15:03                         ` Aldy Hernandez
2001-11-13 15:03                           ` Alan Matsuoka
2001-11-13 15:03                     ` Alan Matsuoka
2001-11-13  4:32                   ` Alan Matsuoka
2001-11-13 15:03                   ` Alan Matsuoka
2001-11-13  4:32                 ` Joseph S. Myers
2001-11-13 15:03                 ` Joseph S. Myers
2001-11-13  4:32               ` Alan Matsuoka
2001-11-13 15:03               ` Alan Matsuoka
2001-11-13  4:32             ` Joseph S. Myers
2001-11-13 15:03             ` Joseph S. Myers
2001-11-05 18:58           ` Aldy Hernandez
2001-11-05 19:01             ` Alan Matsuoka
2001-11-13  4:32               ` Alan Matsuoka
2001-11-13 15:03               ` Alan Matsuoka
2001-11-05 21:37             ` Alan Matsuoka
2001-11-13  4:32               ` Alan Matsuoka
2001-11-13 15:03               ` Alan Matsuoka
2001-11-13  4:32             ` Aldy Hernandez
2001-11-13 15:03             ` Aldy Hernandez
2001-11-06  0:23           ` Gerald Pfeifer
2001-11-13  4:32             ` Gerald Pfeifer
2001-11-13 15:03             ` Gerald Pfeifer
2001-11-13  4:32           ` Alan Matsuoka
2001-11-13 15:03           ` Alan Matsuoka
2001-11-13  4:32         ` Alan Matsuoka
2001-11-13 15:03         ` Alan Matsuoka
2001-11-13  4:32       ` Aldy Hernandez
2001-11-13 15:03       ` Aldy Hernandez
2001-11-13  4:32     ` Alan Matsuoka
2001-11-13 15:03     ` Alan Matsuoka
2001-11-05 14:31   ` Stan Shebs
2001-11-05 14:49     ` Geoff Keating
2001-11-05 15:29       ` Stan Shebs
2001-11-13  4:32         ` Stan Shebs
2001-11-13 15:03         ` Stan Shebs
2001-11-05 19:30       ` Aldy Hernandez
2001-11-13  4:32         ` Aldy Hernandez
2001-11-13 15:03         ` Aldy Hernandez
2001-11-13  4:32       ` Geoff Keating
2001-11-13 15:03       ` Geoff Keating
2001-11-13  4:32     ` Stan Shebs
2001-11-13 15:03     ` Stan Shebs
2001-11-05 19:27   ` Aldy Hernandez
2001-11-05 20:10     ` Geoff Keating
2001-11-13  4:32       ` Geoff Keating
2001-11-13 15:03       ` Geoff Keating
2001-11-13  4:32     ` Aldy Hernandez
2001-11-13 15:03     ` Aldy Hernandez
2001-11-06 15:02   ` Aldy Hernandez
2001-11-06 15:14     ` Joseph S. Myers
2001-11-06 16:28       ` Aldy Hernandez
2001-11-13  4:33         ` Aldy Hernandez
2001-11-13 15:03         ` Aldy Hernandez
2001-11-13  4:33       ` Joseph S. Myers
2001-11-13 15:03       ` Joseph S. Myers
2001-11-06 17:00     ` Dale Johannesen
2001-11-06 17:06       ` Aldy Hernandez
2001-11-13  4:33         ` Aldy Hernandez
2001-11-13 15:03         ` Aldy Hernandez
2001-11-13  4:33       ` Dale Johannesen
2001-11-13 15:03       ` Dale Johannesen
2001-11-06 17:07     ` Stan Shebs
2001-11-06 17:15       ` Aldy Hernandez
2001-11-13  4:33         ` Aldy Hernandez
2001-11-13 15:03         ` Aldy Hernandez
2001-11-13  4:33       ` Stan Shebs
2001-11-13 15:03       ` Stan Shebs
2001-11-13  4:33     ` Aldy Hernandez
2001-11-13 15:03     ` Aldy Hernandez
2001-11-06 23:17   ` Richard Henderson
2001-11-07  2:50     ` Geoff Keating
2001-11-07  8:30       ` Aldy Hernandez
2001-11-13  4:33         ` Aldy Hernandez
2001-11-13 15:03         ` Aldy Hernandez
2001-11-07 11:41       ` Richard Henderson
2001-11-07 12:12         ` Geoff Keating
2001-11-13  5:05           ` Geoff Keating
2001-11-13 15:03           ` Geoff Keating
2001-11-13  5:05         ` Richard Henderson
2001-11-13 15:03         ` Richard Henderson
2001-11-13  4:33       ` Geoff Keating
2001-11-13 15:03       ` Geoff Keating
2001-11-07  8:23     ` Aldy Hernandez
2001-11-13  4:33       ` Aldy Hernandez
2001-11-13 15:03       ` Aldy Hernandez
2001-11-13  4:33     ` Richard Henderson
2001-11-13 15:03     ` Richard Henderson
2001-11-13  4:32   ` Geoff Keating
2001-11-13 15:03   ` Geoff Keating
2001-11-05 14:05 ` Dale Johannesen
2001-11-05 14:38   ` Geoff Keating
2001-11-13  4:32     ` Geoff Keating
2001-11-13 15:03     ` Geoff Keating
2001-11-05 18:30   ` Aldy Hernandez
2001-11-06 16:12     ` Daniel Jacobowitz
2001-11-06 16:46       ` Aldy Hernandez
2001-11-13  4:33         ` Aldy Hernandez
2001-11-13 15:03         ` Aldy Hernandez
2001-11-07  2:36       ` Geoff Keating
2001-11-13  4:33         ` Geoff Keating
2001-11-13 15:03         ` Geoff Keating
2001-11-13  4:33       ` Daniel Jacobowitz
2001-11-13 15:03       ` Daniel Jacobowitz
2001-11-13  4:32     ` Aldy Hernandez
2001-11-13 15:03     ` Aldy Hernandez
2001-11-05 19:47   ` Aldy Hernandez
2001-11-13  4:32     ` Aldy Hernandez
2001-11-13 15:03     ` Aldy Hernandez
2001-11-13  4:32   ` Dale Johannesen
2001-11-13 15:03   ` Dale Johannesen
2001-11-05 14:39 ` Dale Johannesen
2001-11-05 18:35   ` Aldy Hernandez
2001-11-13  4:32     ` Aldy Hernandez
2001-11-13 15:03     ` Aldy Hernandez
2001-11-13  4:32   ` Dale Johannesen
2001-11-13 15:03   ` Dale Johannesen
2001-11-13  4:32 ` Aldy Hernandez
2001-11-13 15:03 ` Aldy Hernandez
2001-11-07 10:02 David Edelsohn
2001-11-07 10:09 ` Aldy Hernandez
2001-11-07 10:13   ` David Edelsohn
2001-11-07 10:24     ` Aldy Hernandez
2001-11-07 10:26       ` David Edelsohn
2001-11-07 10:34         ` Aldy Hernandez
2001-11-07 14:19           ` David Edelsohn
2001-11-07 14:25             ` Aldy Hernandez
2001-11-13  5:05               ` Aldy Hernandez
2001-11-13 15:03               ` Aldy Hernandez
2001-11-13  5:05             ` David Edelsohn
2001-11-13 15:03             ` David Edelsohn
2001-11-13  4:33           ` Aldy Hernandez
2001-11-13 15:03           ` Aldy Hernandez
2001-11-13  4:33         ` David Edelsohn
2001-11-13 15:03         ` David Edelsohn
2001-11-13  4:33       ` Aldy Hernandez
2001-11-13 15:03       ` Aldy Hernandez
2001-11-07 10:34     ` Dale Johannesen
2001-11-13  4:33       ` Dale Johannesen
2001-11-13 15:03       ` Dale Johannesen
2001-11-13  4:33     ` David Edelsohn
2001-11-13 15:03     ` David Edelsohn
2001-11-13  4:33   ` Aldy Hernandez
2001-11-13 15:03   ` Aldy Hernandez
2001-11-07 10:16 ` Dale Johannesen
2001-11-13  4:33   ` Dale Johannesen
2001-11-13 15:03   ` Dale Johannesen
2001-11-13  4:33 ` David Edelsohn
2001-11-13 15:03 ` David Edelsohn
2001-11-08 14:33 David Edelsohn
2001-11-13  5:26 ` David Edelsohn
2001-11-13 15:03 ` David Edelsohn

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).