Alpha CPU-specific builtins

Richard Henderson rth@redhat.com
Mon Jun 3 21:13:00 GMT 2002


I have need of some builtins myself, so I went ahead and 
finished up your current patch.  Changes since your last:

  * alpha_expand_zap_mask needs to return an rtx, so that we
    can cross-compile from 32-bit and return a CONST_DOUBLE.

  * alpha_init_builtins, alpha_expand_builtin use tables.

  * alpha_expand_builtin_vector_binop elimiates lots of
    duplicate code in md file.

  * vector move patterns implemented.

  * extql extqh mind endianness.

  * pklb, pkwb, unpkbl, unpkbw expressed as vector operations.

  * documentation written.

  * test cases written.


r~


        * config/alpha/alpha.c (reg_or_const_int_operand): New.
        (some_operand, input_operand): Accept CONST_VECTOR.
        (alpha_extra_constraint): Add 'W'.
        (alpha_expand_zap_mask): New.
        (alpha_expand_builtin_vector_binop): New.
        (enum alpha_builtin): New.
        (zero_arg_builtins, one_arg_builtins, two_arg_builtins): New.
        (alpha_init_builtins, alpha_expand_builtin): New.
        (TARGET_INIT_BUILTINS, TARGET_EXPAND_BUILTIN): New.
        * config/alpha/alpha.h (VECTOR_MODE_SUPPORTED_P): New.
        (PREDICATE_CODES): Update.
        * config/alpha/alpha-protos.h: Update.
        * config/alpha/alpha.md (UNSPEC_CMPBGE, UNSPEC_ZAP,
        UNSPEC_AMASK, UNSPEC_IMPLVER, UNSPEC_PERR, UNSPECV_RPCC): New.
        (movv8qi, movv8qi_fix, movv8qi_nofix): New.
        (movv4hi, movv4hi_fix, movv4hi_nofix): New.
        (movv2si, movv2si_fix, movv2si_nofix): New.
        (uminv8qi3, sminv8qi3, uminv4hi3, sminv4hi3): New.
        (umaxv8qi3, smaxv8qi3, umaxv4hi3, smaxv4hi3): New.
        (builtin_cmpbge, builtin_extql, builtin_extqh, builtin_zap,
        builtin_zap_1, builtin_zapnot, builtin_zapnot_1, builtin_amask,
        builtin_implver, builtin_rpcc, builtin_minub8, builtin_minsb8,
        builtin_minuw4, builtin_minsw4, builtin_maxub8, builtin_maxsb8,
        builtin_maxuw4, builtin_maxsw4, builtin_perr, builtin_pklb,
        pklb, builtin_pkwb, pkwb, builtin_unpkbl, unpkbl,
        builtin_unpkbw, unpkbw): New.
        * doc/extend.texi (Alpha Built-in Functions): New.

        * gcc.dg/alpha-base-1.c, gcc.dg/alpha-base-2.c: New.
        * gcc.dg/alpha-max-1.c, gcc.dg/alpha-max-2.c: New.

Index: config/alpha/alpha-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha-protos.h,v
retrieving revision 1.36
diff -c -p -d -r1.36 alpha-protos.h
*** config/alpha/alpha-protos.h	4 Jun 2002 02:36:36 -0000	1.36
--- config/alpha/alpha-protos.h	4 Jun 2002 03:57:35 -0000
*************** extern void alpha_output_lineno PARAMS (
*** 37,42 ****
--- 37,43 ----
  extern int reg_or_0_operand PARAMS ((rtx, enum machine_mode));
  extern int reg_or_6bit_operand PARAMS ((rtx, enum machine_mode));
  extern int reg_or_8bit_operand PARAMS ((rtx, enum machine_mode));
+ extern int reg_or_const_int_operand PARAMS ((rtx, enum machine_mode));
  extern int cint8_operand PARAMS ((rtx, enum machine_mode));
  extern int add_operand PARAMS ((rtx, enum machine_mode));
  extern int sext_add_operand PARAMS ((rtx, enum machine_mode));
*************** extern void alpha_expand_unaligned_store
*** 122,127 ****
--- 123,132 ----
  						 HOST_WIDE_INT));
  extern int alpha_expand_block_move PARAMS ((rtx []));
  extern int alpha_expand_block_clear PARAMS ((rtx []));
+ extern rtx alpha_expand_zap_mask PARAMS ((HOST_WIDE_INT));
+ extern void alpha_expand_builtin_vector_binop PARAMS ((rtx (*)(rtx, rtx, rtx),
+ 						       enum machine_mode,
+ 						       rtx, rtx, rtx));
  extern rtx alpha_return_addr PARAMS ((int, rtx));
  extern rtx alpha_gp_save_rtx PARAMS ((void));
  extern void print_operand PARAMS ((FILE *, rtx, int));
Index: config/alpha/alpha.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.c,v
retrieving revision 1.257
diff -c -p -d -r1.257 alpha.c
*** config/alpha/alpha.c	4 Jun 2002 02:28:39 -0000	1.257
--- config/alpha/alpha.c	4 Jun 2002 03:57:35 -0000
*************** static void alpha_expand_unaligned_load_
*** 142,147 ****
--- 142,151 ----
    PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
  static void alpha_expand_unaligned_store_words
    PARAMS ((rtx *out_regs, rtx smem, HOST_WIDE_INT words, HOST_WIDE_INT ofs));
+ static void alpha_init_builtins
+   PARAMS ((void));
+ static rtx alpha_expand_builtin
+   PARAMS ((tree, rtx, rtx, enum machine_mode, int));
  static void alpha_sa_mask
    PARAMS ((unsigned long *imaskP, unsigned long *fmaskP));
  static int find_lo_sum
*************** static void unicosmk_unique_section PARA
*** 278,283 ****
--- 282,292 ----
  #undef TARGET_HAVE_TLS
  #define TARGET_HAVE_TLS HAVE_AS_TLS
  
+ #undef  TARGET_INIT_BUILTINS
+ #define TARGET_INIT_BUILTINS alpha_init_builtins
+ #undef  TARGET_EXPAND_BUILTIN
+ #define TARGET_EXPAND_BUILTIN alpha_expand_builtin
+ 
  struct gcc_target targetm = TARGET_INITIALIZER;
  
  /* Parse target option strings.  */
*************** reg_or_8bit_operand (op, mode)
*** 610,615 ****
--- 619,634 ----
  	  || register_operand (op, mode));
  }
  
+ /* Return 1 if OP is a constant or any register.  */
+ 
+ int
+ reg_or_const_int_operand (op, mode)
+      register rtx op;
+      enum machine_mode mode;
+ {
+   return GET_CODE (op) == CONST_INT || register_operand (op, mode);
+ }
+ 
  /* Return 1 if OP is an 8-bit constant.  */
  
  int
*************** some_operand (op, mode)
*** 813,820 ****
  
    switch (GET_CODE (op))
      {
!     case REG:  case MEM:  case CONST_DOUBLE:  case CONST_INT:  case LABEL_REF:
!     case SYMBOL_REF:  case CONST:  case HIGH:
        return 1;
  
      case SUBREG:
--- 832,846 ----
  
    switch (GET_CODE (op))
      {
!     case REG:
!     case MEM:
!     case CONST_INT:
!     case CONST_DOUBLE:
!     case CONST_VECTOR:
!     case LABEL_REF:
!     case SYMBOL_REF:
!     case CONST:
!     case HIGH:
        return 1;
  
      case SUBREG:
*************** input_operand (op, mode)
*** 893,899 ****
  	      && general_operand (op, mode));
  
      case CONST_DOUBLE:
!       return GET_MODE_CLASS (mode) == MODE_FLOAT && op == CONST0_RTX (mode);
  
      case CONST_INT:
        return mode == QImode || mode == HImode || add_operand (op, mode);
--- 919,926 ----
  	      && general_operand (op, mode));
  
      case CONST_DOUBLE:
!     case CONST_VECTOR:
!       return op == CONST0_RTX (mode);
  
      case CONST_INT:
        return mode == QImode || mode == HImode || add_operand (op, mode);
*************** alpha_extra_constraint (value, c)
*** 1615,1621 ****
        return GET_CODE (value) == HIGH;
      case 'U':
        return TARGET_ABI_UNICOSMK && symbolic_operand (value, VOIDmode);
! 
      default:
        return false;
      }
--- 1642,1650 ----
        return GET_CODE (value) == HIGH;
      case 'U':
        return TARGET_ABI_UNICOSMK && symbolic_operand (value, VOIDmode);
!     case 'W':
!       return (GET_CODE (value) == CONST_VECTOR
! 	      && value == CONST0_RTX (GET_MODE (value)));
      default:
        return false;
      }
*************** alpha_expand_block_clear (operands)
*** 5147,5152 ****
--- 5176,5249 ----
  
    return 1;
  }
+ 
+ /* Returns a mask so that zap(x, value) == x & mask.  */
+ 
+ rtx
+ alpha_expand_zap_mask (value)
+      HOST_WIDE_INT value;
+ {
+   rtx result;
+   int i;
+ 
+   if (HOST_BITS_PER_WIDE_INT >= 64)
+     {
+       HOST_WIDE_INT mask = 0;
+ 
+       for (i = 7; i >= 0; --i)
+ 	{
+ 	  mask <<= 8;
+ 	  if (!((value >> i) & 1))
+ 	    mask |= 0xff;
+ 	}
+ 
+       result = gen_int_mode (mask, DImode);
+     }
+   else if (HOST_BITS_PER_WIDE_INT == 32)
+     {
+       HOST_WIDE_INT mask_lo = 0, mask_hi = 0;
+ 
+       for (i = 7; i >= 4; --i)
+ 	{
+ 	  mask_hi <<= 8;
+ 	  if (!((value >> i) & 1))
+ 	    mask_hi |= 0xff;
+ 	}
+ 
+       for (i = 3; i >= 0; --i)
+ 	{
+ 	  mask_lo <<= 8;
+ 	  if (!((value >> i) & 1))
+ 	    mask_lo |= 0xff;
+ 	}
+ 
+       result = immed_double_const (mask_lo, mask_hi, DImode);
+     }
+   else
+     abort ();
+ 
+   return result;
+ }
+ 
+ void
+ alpha_expand_builtin_vector_binop (gen, mode, op0, op1, op2)
+      rtx (*gen) PARAMS ((rtx, rtx, rtx));
+      enum machine_mode mode;
+      rtx op0, op1, op2;
+ {
+   op0 = gen_lowpart (mode, op0);
+ 
+   if (op1 == const0_rtx)
+     op1 = CONST0_RTX (mode);
+   else
+     op1 = gen_lowpart (mode, op1);
+   if (op1 == const0_rtx)
+     op2 = CONST0_RTX (mode);
+   else
+     op2 = gen_lowpart (mode, op2);
+ 
+   emit_insn ((*gen) (op0, op1, op2));
+ }
  
  /* Adjust the cost of a scheduling dependency.  Return the new cost of
     a dependency LINK or INSN on DEP_INSN.  COST is the current cost.  */
*************** alpha_va_arg (valist, type)
*** 6259,6264 ****
--- 6356,6566 ----
      }
  
    return addr;
+ }
+ 
+ /* Builtins.  */
+ 
+ enum alpha_builtin
+ {
+   ALPHA_BUILTIN_CMPBGE,
+   ALPHA_BUILTIN_EXTQL,
+   ALPHA_BUILTIN_EXTQH,
+   ALPHA_BUILTIN_ZAP,
+   ALPHA_BUILTIN_ZAPNOT,
+   ALPHA_BUILTIN_AMASK,
+   ALPHA_BUILTIN_IMPLVER,
+   ALPHA_BUILTIN_RPCC,
+ 
+   /* TARGET_MAX */
+   ALPHA_BUILTIN_MINUB8,
+   ALPHA_BUILTIN_MINSB8,
+   ALPHA_BUILTIN_MINUW4,
+   ALPHA_BUILTIN_MINSW4,
+   ALPHA_BUILTIN_MAXUB8,
+   ALPHA_BUILTIN_MAXSB8,
+   ALPHA_BUILTIN_MAXUW4,
+   ALPHA_BUILTIN_MAXSW4,
+   ALPHA_BUILTIN_PERR,
+   ALPHA_BUILTIN_PKLB,
+   ALPHA_BUILTIN_PKWB,
+   ALPHA_BUILTIN_UNPKBL,
+   ALPHA_BUILTIN_UNPKBW,
+ 
+   ALPHA_BUILTIN_max
+ };
+ 
+ struct alpha_builtin_def
+ {
+   const char *name;
+   enum alpha_builtin code;
+   unsigned int target_mask;
+ };
+ 
+ static struct alpha_builtin_def const zero_arg_builtins[] = {
+   { "__builtin_alpha_implver",	ALPHA_BUILTIN_IMPLVER,	0 },
+   { "__builtin_alpha_rpcc",	ALPHA_BUILTIN_RPCC,	0 }
+ };
+ 
+ static struct alpha_builtin_def const one_arg_builtins[] = {
+   { "__builtin_alpha_amask",	ALPHA_BUILTIN_AMASK,	0 },
+   { "__builtin_alpha_pklb",	ALPHA_BUILTIN_PKLB,	MASK_MAX },
+   { "__builtin_alpha_pkwb",	ALPHA_BUILTIN_PKWB,	MASK_MAX },
+   { "__builtin_alpha_unpkbl",	ALPHA_BUILTIN_UNPKBL,	MASK_MAX },
+   { "__builtin_alpha_unpkbw",	ALPHA_BUILTIN_UNPKBW,	MASK_MAX }
+ };
+ 
+ static struct alpha_builtin_def const two_arg_builtins[] = {
+   { "__builtin_alpha_cmpbge",	ALPHA_BUILTIN_CMPBGE,	0 },
+   { "__builtin_alpha_extql",	ALPHA_BUILTIN_EXTQL,	0 },
+   { "__builtin_alpha_extqh",	ALPHA_BUILTIN_EXTQH,	0 },
+   { "__builtin_alpha_zap",	ALPHA_BUILTIN_ZAP,	0 },
+   { "__builtin_alpha_zapnot",	ALPHA_BUILTIN_ZAPNOT,	0 },
+   { "__builtin_alpha_minub8",	ALPHA_BUILTIN_MINUB8,	MASK_MAX },
+   { "__builtin_alpha_minsb8",	ALPHA_BUILTIN_MINSB8,	MASK_MAX },
+   { "__builtin_alpha_minuw4",	ALPHA_BUILTIN_MINUW4,	MASK_MAX },
+   { "__builtin_alpha_minsw4",	ALPHA_BUILTIN_MINSW4,	MASK_MAX },
+   { "__builtin_alpha_maxub8",	ALPHA_BUILTIN_MAXUB8,	MASK_MAX },
+   { "__builtin_alpha_maxsb8",	ALPHA_BUILTIN_MAXSB8,	MASK_MAX },
+   { "__builtin_alpha_maxuw4",	ALPHA_BUILTIN_MAXUW4,	MASK_MAX },
+   { "__builtin_alpha_maxsw4",	ALPHA_BUILTIN_MAXSW4,	MASK_MAX },
+   { "__builtin_alpha_perr",	ALPHA_BUILTIN_PERR,	MASK_MAX }
+ };
+ 
+ static void
+ alpha_init_builtins ()
+ {
+   const struct alpha_builtin_def *p;
+   tree ftype;
+   size_t i;
+ 
+   ftype = build_function_type (long_integer_type_node, void_list_node);
+ 
+   p = zero_arg_builtins;
+   for (i = 0; i < ARRAY_SIZE (zero_arg_builtins); ++i, ++p)
+     if ((target_flags & p->target_mask) == p->target_mask)
+       builtin_function (p->name, ftype, p->code, BUILT_IN_MD, NULL);
+ 
+   ftype = build_function_type (long_integer_type_node,
+ 			       tree_cons (NULL_TREE,
+ 					  long_integer_type_node,
+ 					  void_list_node));
+ 
+   p = one_arg_builtins;
+   for (i = 0; i < ARRAY_SIZE (one_arg_builtins); ++i, ++p)
+     if ((target_flags & p->target_mask) == p->target_mask)
+       builtin_function (p->name, ftype, p->code, BUILT_IN_MD, NULL);
+ 
+   ftype = build_function_type (long_integer_type_node,
+ 			       tree_cons (NULL_TREE,
+ 					  long_integer_type_node,
+ 					  tree_cons (NULL_TREE,
+ 						     long_integer_type_node,
+ 						     void_list_node)));
+ 
+   p = two_arg_builtins;
+   for (i = 0; i < ARRAY_SIZE (two_arg_builtins); ++i, ++p)
+     if ((target_flags & p->target_mask) == p->target_mask)
+       builtin_function (p->name, ftype, p->code, BUILT_IN_MD, NULL);
+ }
+ 
+ /* 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
+ alpha_expand_builtin (exp, target, subtarget, mode, ignore)
+      tree exp;
+      rtx target;
+      rtx subtarget ATTRIBUTE_UNUSED;
+      enum machine_mode mode ATTRIBUTE_UNUSED;
+      int ignore ATTRIBUTE_UNUSED;
+ {
+   static unsigned int const code_for_builtin[ALPHA_BUILTIN_max] = {
+     CODE_FOR_builtin_cmpbge,
+     CODE_FOR_builtin_extql,
+     CODE_FOR_builtin_extqh,
+     CODE_FOR_builtin_zap,
+     CODE_FOR_builtin_zapnot,
+     CODE_FOR_builtin_amask,
+     CODE_FOR_builtin_implver,
+     CODE_FOR_builtin_rpcc,
+     CODE_FOR_builtin_minub8,
+     CODE_FOR_builtin_minsb8,
+     CODE_FOR_builtin_minuw4,
+     CODE_FOR_builtin_minsw4,
+     CODE_FOR_builtin_maxub8,
+     CODE_FOR_builtin_maxsb8,
+     CODE_FOR_builtin_maxuw4,
+     CODE_FOR_builtin_maxsw4,
+     CODE_FOR_builtin_perr,
+     CODE_FOR_builtin_pklb,
+     CODE_FOR_builtin_pkwb,
+     CODE_FOR_builtin_unpkbl,
+     CODE_FOR_builtin_unpkbw,
+   };
+ 
+ #define MAX_ARGS 2
+ 
+   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+   tree arglist = TREE_OPERAND (exp, 1);
+   enum insn_code icode;
+   rtx op[MAX_ARGS], pat;
+   int arity;
+   enum machine_mode tmode;
+ 
+   if (fcode >= ALPHA_BUILTIN_max)
+     internal_error ("bad builtin fcode");
+   icode = code_for_builtin[fcode];
+   if (icode == 0)
+     internal_error ("bad builtin fcode");
+ 
+   for (arglist = TREE_OPERAND (exp, 1), arity = 0;
+        arglist;
+        arglist = TREE_CHAIN (arglist), arity++)
+     {
+       const struct insn_operand_data *insn_op;
+ 
+       tree arg = TREE_VALUE (arglist);
+       if (arg == error_mark_node)
+ 	return NULL_RTX;
+       if (arity > MAX_ARGS)
+ 	return NULL_RTX;
+ 
+       op[arity] = expand_expr (arg, NULL_RTX, VOIDmode, 0);
+ 
+       insn_op = &insn_data[icode].operand[arity];
+       if (!(*insn_op->predicate) (op[arity], insn_op->mode))
+ 	op[arity] = copy_to_mode_reg (insn_op->mode, op[arity]);
+     }
+ 
+   tmode = insn_data[icode].operand[0].mode;
+   if (!target
+       || GET_MODE (target) != tmode
+       || !(*insn_data[icode].operand[0].predicate) (target, tmode))
+     target = gen_reg_rtx (tmode);
+ 
+   switch (arity)
+     {
+     case 0:
+       pat = GEN_FCN (icode) (target);
+       break;
+     case 1:
+       pat = GEN_FCN (icode) (target, op[0]);
+       break;
+     case 2:
+       pat = GEN_FCN (icode) (target, op[0], op[1]);
+       break;
+     default:
+       abort ();
+     }
+   if (!pat)
+     return NULL_RTX;
+   emit_insn (pat);
+ 
+   return target;
  }
  
  /* This page contains routines that are used to determine what the function
Index: config/alpha/alpha.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.h,v
retrieving revision 1.169
diff -c -p -d -r1.169 alpha.h
*** config/alpha/alpha.h	4 Jun 2002 02:28:40 -0000	1.169
--- config/alpha/alpha.h	4 Jun 2002 03:57:36 -0000
*************** extern const char *alpha_tls_size_string
*** 615,620 ****
--- 615,626 ----
     ? GET_MODE_UNIT_SIZE (MODE) == 8 || GET_MODE_UNIT_SIZE (MODE) == 4	\
     : 1)
  
+ /* Value is 1 if MODE is a supported vector mode.  */
+ 
+ #define VECTOR_MODE_SUPPORTED_P(MODE) \
+   (TARGET_MAX \
+    && ((MODE) == V8QImode || (MODE) == V4HImode || (MODE) == V2SImode))
+ 
  /* A C expression that is nonzero if a value of mode
     MODE1 is accessible in mode MODE2 without copying.
  
*************** enum reg_class {
*** 789,795 ****
  
     'T' is a HIGH.
  
!    'U' is a symbolic operand.  */
  
  #define EXTRA_CONSTRAINT  alpha_extra_constraint
  
--- 795,803 ----
  
     'T' is a HIGH.
  
!    'U' is a symbolic operand.
! 
!    'W' is a vector zero.   */
  
  #define EXTRA_CONSTRAINT  alpha_extra_constraint
  
*************** do {						\
*** 1923,1928 ****
--- 1931,1937 ----
  			CONST_VECTOR}},					\
    {"reg_or_6bit_operand", {SUBREG, REG, CONST_INT}},			\
    {"reg_or_8bit_operand", {SUBREG, REG, CONST_INT}},			\
+   {"reg_or_const_int_operand", {SUBREG, REG, CONST_INT}},		\
    {"cint8_operand", {CONST_INT}},					\
    {"reg_or_cint_operand", {SUBREG, REG, CONST_INT}},			\
    {"add_operand", {SUBREG, REG, CONST_INT}},				\
*************** do {						\
*** 1953,1961 ****
    {"gottp_symbolic_operand", {CONST}},					\
    {"call_operand", {REG, SYMBOL_REF}},					\
    {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,		\
! 		     SYMBOL_REF, CONST, LABEL_REF, HIGH}},		\
    {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,		\
! 		    SYMBOL_REF, CONST, LABEL_REF, HIGH}},		\
    {"some_ni_operand", {SUBREG, REG, MEM}},				\
    {"aligned_memory_operand", {MEM}},					\
    {"unaligned_memory_operand", {MEM}},					\
--- 1962,1970 ----
    {"gottp_symbolic_operand", {CONST}},					\
    {"call_operand", {REG, SYMBOL_REF}},					\
    {"input_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,		\
! 		     CONST_VECTOR, SYMBOL_REF, CONST, LABEL_REF, HIGH}},\
    {"some_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE,		\
! 		    CONST_VECTOR, SYMBOL_REF, CONST, LABEL_REF, HIGH}},	\
    {"some_ni_operand", {SUBREG, REG, MEM}},				\
    {"aligned_memory_operand", {MEM}},					\
    {"unaligned_memory_operand", {MEM}},					\
Index: config/alpha/alpha.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/alpha/alpha.md,v
retrieving revision 1.189
diff -c -p -d -r1.189 alpha.md
*** config/alpha/alpha.md	4 Jun 2002 02:28:40 -0000	1.189
--- config/alpha/alpha.md	4 Jun 2002 03:57:36 -0000
***************
*** 49,54 ****
--- 49,61 ----
     (UNSPEC_DTPREL	19)
     (UNSPEC_TPREL	20)
     (UNSPEC_TP		21)
+ 
+    ;; Builtins
+    (UNSPEC_CMPBGE	22)
+    (UNSPEC_ZAP		23)
+    (UNSPEC_AMASK	24)
+    (UNSPEC_IMPLVER	25)
+    (UNSPEC_PERR		26)
    ])
  
  ;; UNSPEC_VOLATILE:
***************
*** 67,72 ****
--- 74,80 ----
     (UNSPECV_LDGP1	10)
     (UNSPECV_PLDGP2	11)	; prologue ldgp
     (UNSPECV_SET_TP	12)
+    (UNSPECV_RPCC	13)
    ])
  
  ;; Where necessary, the suffixes _le and _be are used to distinguish between
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 6111,6116 ****
--- 6119,6313 ----
    DONE;
  })
  
+ ;; Vector operations
+ 
+ (define_expand "movv8qi"
+   [(set (match_operand:V8QI 0 "nonimmediate_operand" "")
+         (match_operand:V8QI 1 "general_operand" ""))]
+   ""
+ {
+   if (alpha_expand_mov (V8QImode, operands))
+     DONE;
+ })
+ 
+ (define_insn "*movv8qi_fix"
+   [(set (match_operand:V8QI 0 "nonimmediate_operand" "=r,r,m,*f,*f,m,r,*f")
+ 	(match_operand:V8QI 1 "input_operand" "rW,m,rW,*fW,m,*f,*f,r"))]
+   "TARGET_FIX
+    && (register_operand (operands[0], V8QImode)
+        || reg_or_0_operand (operands[1], V8QImode))"
+   "@
+    bis $31,%r1,%0
+    ldq %0,%1
+    stq %r1,%0
+    cpys %R1,%R1,%0
+    ldt %0,%1
+    stt %R1,%0
+    ftoit %1,%0
+    itoft %1,%0"
+   [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst,ftoi,itof")])
+ 
+ (define_insn "*movv8qi_nofix"
+   [(set (match_operand:V8QI 0 "nonimmediate_operand" "=r,r,m,*f,*f,m")
+ 	(match_operand:V8QI 1 "input_operand" "rW,m,rW,*fW,m,*f"))]
+   "! TARGET_FIX
+    && (register_operand (operands[0], V8QImode)
+        || reg_or_0_operand (operands[1], V8QImode))"
+   "@
+    bis $31,%r1,%0
+    ldq %0,%1
+    stq %r1,%0
+    cpys %R1,%R1,%0
+    ldt %0,%1
+    stt %R1,%0"
+   [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst")])
+ 
+ (define_expand "movv4hi"
+   [(set (match_operand:V4HI 0 "nonimmediate_operand" "")
+         (match_operand:V4HI 1 "general_operand" ""))]
+   ""
+ {
+   if (alpha_expand_mov (V4HImode, operands))
+     DONE;
+ })
+ 
+ (define_insn "*movv4hi_fix"
+   [(set (match_operand:V4HI 0 "nonimmediate_operand" "=r,r,m,*f,*f,m,r,*f")
+ 	(match_operand:V4HI 1 "input_operand" "rW,m,rW,*fW,m,*f,*f,r"))]
+   "TARGET_FIX
+    && (register_operand (operands[0], V4HImode)
+        || reg_or_0_operand (operands[1], V4HImode))"
+   "@
+    bis $31,%r1,%0
+    ldq %0,%1
+    stq %r1,%0
+    cpys %R1,%R1,%0
+    ldt %0,%1
+    stt %R1,%0
+    ftoit %1,%0
+    itoft %1,%0"
+   [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst,ftoi,itof")])
+ 
+ (define_insn "*movv4hi_nofix"
+   [(set (match_operand:V4HI 0 "nonimmediate_operand" "=r,r,m,*f,*f,m")
+ 	(match_operand:V4HI 1 "input_operand" "rW,m,rW,*fW,m,*f"))]
+   "! TARGET_FIX
+    && (register_operand (operands[0], V4HImode)
+        || reg_or_0_operand (operands[1], V4HImode))"
+   "@
+    bis $31,%r1,%0
+    ldq %0,%1
+    stq %r1,%0
+    cpys %R1,%R1,%0
+    ldt %0,%1
+    stt %R1,%0"
+   [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst")])
+ 
+ (define_expand "movv2si"
+   [(set (match_operand:V2SI 0 "nonimmediate_operand" "")
+         (match_operand:V2SI 1 "general_operand" ""))]
+   ""
+ {
+   if (alpha_expand_mov (V2SImode, operands))
+     DONE;
+ })
+ 
+ (define_insn "*movv2si_fix"
+   [(set (match_operand:V2SI 0 "nonimmediate_operand" "=r,r,m,*f,*f,m,r,*f")
+ 	(match_operand:V2SI 1 "input_operand" "rW,m,rW,*fW,m,*f,*f,r"))]
+   "TARGET_FIX
+    && (register_operand (operands[0], V2SImode)
+        || reg_or_0_operand (operands[1], V2SImode))"
+   "@
+    bis $31,%r1,%0
+    ldq %0,%1
+    stq %r1,%0
+    cpys %R1,%R1,%0
+    ldt %0,%1
+    stt %R1,%0
+    ftoit %1,%0
+    itoft %1,%0"
+   [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst,ftoi,itof")])
+ 
+ (define_insn "*movv2si_nofix"
+   [(set (match_operand:V2SI 0 "nonimmediate_operand" "=r,r,m,*f,*f,m")
+ 	(match_operand:V2SI 1 "input_operand" "rW,m,rW,*fW,m,*f"))]
+   "! TARGET_FIX
+    && (register_operand (operands[0], V2SImode)
+        || reg_or_0_operand (operands[1], V2SImode))"
+   "@
+    bis $31,%r1,%0
+    ldq %0,%1
+    stq %r1,%0
+    cpys %R1,%R1,%0
+    ldt %0,%1
+    stt %R1,%0"
+   [(set_attr "type" "ilog,ild,ist,fcpys,fld,fst")])
+ 
+ (define_insn "uminv8qi3"
+   [(set (match_operand:V8QI 0 "register_operand" "=r")
+ 	(umin:V8QI (match_operand:V8QI 1 "reg_or_0_operand" "rW")
+ 		   (match_operand:V8QI 2 "reg_or_0_operand" "rW")))]
+   "TARGET_MAX"
+   "minub8 %r1,%r2,%0"
+   [(set_attr "type" "mvi")])
+ 
+ (define_insn "sminv8qi3"
+   [(set (match_operand:V8QI 0 "register_operand" "=r")
+ 	(smin:V8QI (match_operand:V8QI 1 "reg_or_0_operand" "rW")
+ 		   (match_operand:V8QI 2 "reg_or_0_operand" "rW")))]
+   "TARGET_MAX"
+   "minsb8 %r1,%r2,%0"
+   [(set_attr "type" "mvi")])
+ 
+ (define_insn "uminv4hi3"
+   [(set (match_operand:V4HI 0 "register_operand" "=r")
+ 	(umin:V4HI (match_operand:V4HI 1 "reg_or_0_operand" "rW")
+ 		   (match_operand:V4HI 2 "reg_or_0_operand" "rW")))]
+   "TARGET_MAX"
+   "minuw4 %r1,%r2,%0"
+   [(set_attr "type" "mvi")])
+ 
+ (define_insn "sminv4hi3"
+   [(set (match_operand:V4HI 0 "register_operand" "=r")
+ 	(smin:V4HI (match_operand:V4HI 1 "reg_or_0_operand" "rW")
+ 		   (match_operand:V4HI 2 "reg_or_0_operand" "rW")))]
+   "TARGET_MAX"
+   "minsw4 %r1,%r2,%0"
+   [(set_attr "type" "mvi")])
+ 
+ (define_insn "umaxv8qi3"
+   [(set (match_operand:V8QI 0 "register_operand" "=r")
+ 	(umax:V8QI (match_operand:V8QI 1 "reg_or_0_operand" "rW")
+ 		   (match_operand:V8QI 2 "reg_or_0_operand" "rW")))]
+   "TARGET_MAX"
+   "maxub8 %r1,%r2,%0"
+   [(set_attr "type" "mvi")])
+ 
+ (define_insn "smaxv8qi3"
+   [(set (match_operand:V8QI 0 "register_operand" "=r")
+ 	(smax:V8QI (match_operand:V8QI 1 "reg_or_0_operand" "rW")
+ 		   (match_operand:V8QI 2 "reg_or_0_operand" "rW")))]
+   "TARGET_MAX"
+   "maxsb8 %r1,%r2,%0"
+   [(set_attr "type" "mvi")])
+ 
+ (define_insn "umaxv4hi3"
+   [(set (match_operand:V4HI 0 "register_operand" "=r")
+ 	(umax:V4HI (match_operand:V4HI 1 "reg_or_0_operand" "rW")
+ 		   (match_operand:V4HI 2 "reg_or_0_operand" "rW")))]
+   "TARGET_MAX"
+   "maxuw4 %r1,%r2,%0"
+   [(set_attr "type" "mvi")])
+ 
+ (define_insn "smaxv4hi3"
+   [(set (match_operand:V4HI 0 "register_operand" "=r")
+ 	(smax:V4HI (match_operand:V4HI 1 "reg_or_0_operand" "rW")
+ 		   (match_operand:V4HI 2 "reg_or_0_operand" "rW")))]
+   "TARGET_MAX"
+   "maxsw4 %r1,%r2,%0"
+   [(set_attr "type" "mvi")])
+ 
  ;; Bit field extract patterns which use ext[wlq][lh]
  
  (define_expand "extv"
*************** fadd,fmul,fcpys,fdiv,fsqrt,misc,mvi,ftoi
*** 6779,6785 ****
--- 6976,7372 ----
    else
      return ".align %0 #realign";
  })
+ 
+ ;; Instructions to be emitted from __builtins.
  
+ (define_insn "builtin_cmpbge"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(unspec:DI [(match_operand:DI 1 "reg_or_0_operand" "rJ")
+ 		    (match_operand:DI 2 "reg_or_8bit_operand" "rI")]
+ 		   UNSPEC_CMPBGE))]
+   ""
+   "cmpbge %r1,%2,%0"
+   ;; The EV6 data sheets list this as ILOG.  OTOH, EV6 doesn't 
+   ;; actually differentiate between ILOG and ICMP in the schedule.
+   [(set_attr "type" "icmp")])
+ 
+ (define_expand "builtin_extql"
+   [(match_operand:DI 0 "register_operand" "")
+    (match_operand:DI 1 "reg_or_0_operand" "")
+    (match_operand:DI 2 "reg_or_8bit_operand" "")]
+   ""
+ {
+   rtx (*gen) PARAMS ((rtx, rtx, rtx, rtx));
+   if (WORDS_BIG_ENDIAN)
+     gen = gen_extxl_be;
+   else
+     gen = gen_extxl_le;
+   emit_insn ((*gen) (operands[0], operands[1], GEN_INT (64), operands[2]));
+   DONE;
+ })
+ 
+ (define_expand "builtin_extqh"
+   [(match_operand:DI 0 "register_operand" "")
+    (match_operand:DI 1 "reg_or_0_operand" "")
+    (match_operand:DI 2 "reg_or_8bit_operand" "")]
+   ""
+ {
+   rtx (*gen) PARAMS ((rtx, rtx, rtx));
+   if (WORDS_BIG_ENDIAN)
+     gen = gen_extqh_be;
+   else
+     gen = gen_extqh_le;
+   emit_insn ((*gen) (operands[0], operands[1], operands[2]));
+   DONE;
+ })
+ 
+ (define_expand "builtin_zap"
+   [(set (match_operand:DI 0 "register_operand" "")
+ 	(and:DI (unspec:DI
+ 		  [(match_operand:DI 2 "reg_or_const_int_operand" "")]
+ 		  UNSPEC_ZAP)
+ 		(match_operand:DI 1 "reg_or_const_int_operand" "")))]
+   ""
+ {
+   if (GET_CODE (operands[2]) == CONST_INT)
+     {
+       rtx mask = alpha_expand_zap_mask (INTVAL (operands[2]));
+ 
+       if (operands[1] == const0_rtx)
+ 	{
+ 	  emit_move_insn (operands[0], const0_rtx);
+ 	  DONE;
+ 	}
+       if (operands[1] == constm1_rtx)
+ 	{
+ 	  emit_move_insn (operands[0], operands[1]);
+ 	  DONE;
+ 	}
+ 
+       operands[1] = force_reg (DImode, operands[1]);
+       emit_insn (gen_anddi3 (operands[0], operands[1], mask));
+       DONE;
+     }
+ 
+   operands[1] = force_reg (DImode, operands[1]);
+   operands[2] = gen_lowpart (QImode, operands[2]);
+ })
+ 
+ (define_insn "*builtin_zap_1"
+   [(set (match_operand:DI 0 "register_operand" "=r,r,r,r")
+ 	(and:DI (unspec:DI
+ 		  [(match_operand:QI 2 "reg_or_const_int_operand" "n,n,r,r")]
+ 		  UNSPEC_ZAP)
+ 		(match_operand:DI 1 "reg_or_const_int_operand" "n,r,J,r")))]
+   ""
+   "@
+    #
+    #
+    bis $31,$31,%0
+    zap %r1,%2,%0"
+   [(set_attr "type" "shift,shift,ilog,shift")])
+ 
+ (define_split
+   [(set (match_operand:DI 0 "register_operand" "")
+ 	(and:DI (unspec:DI
+ 		  [(match_operand:QI 2 "const_int_operand" "")]
+ 		  UNSPEC_ZAP)
+ 		(match_operand:DI 1 "const_int_operand" "")))]
+   ""
+   [(const_int 0)]
+ {
+   rtx mask = alpha_expand_zap_mask (INTVAL (operands[2]));
+   if (HOST_BITS_PER_WIDE_INT >= 64 || GET_CODE (mask) == CONST_INT)
+     operands[1] = gen_int_mode (INTVAL (operands[1]) & INTVAL (mask), DImode);
+   else
+     {
+       HOST_WIDE_INT c_lo = INTVAL (operands[1]);
+       HOST_WIDE_INT c_hi = (c_lo < 0 ? -1 : 0);
+       operands[1] = immed_double_const (c_lo & CONST_DOUBLE_LOW (mask),
+ 					c_hi & CONST_DOUBLE_HIGH (mask),
+ 					DImode);
+     }
+   emit_move_insn (operands[0], operands[1]);
+   DONE;
+ })
+ 
+ (define_split
+   [(set (match_operand:DI 0 "register_operand" "")
+ 	(and:DI (unspec:DI
+ 		  [(match_operand:QI 2 "const_int_operand" "")]
+ 		  UNSPEC_ZAP)
+ 		(match_operand:DI 1 "register_operand" "")))]
+   ""
+   [(set (match_dup 0)
+ 	(and:DI (match_dup 1) (match_dup 2)))]
+ {
+   operands[2] = alpha_expand_zap_mask (INTVAL (operands[2]));
+   if (operands[2] == const0_rtx)
+     {
+       emit_move_insn (operands[0], const0_rtx);
+       DONE;
+     }
+   if (operands[2] == constm1_rtx)
+     {
+       emit_move_insn (operands[0], operands[1]);
+       DONE;
+     }
+ })
+ 
+ (define_expand "builtin_zapnot"
+   [(set (match_operand:DI 0 "register_operand" "")
+ 	(and:DI (unspec:DI
+ 		  [(not:QI (match_operand:QI 2 "reg_or_const_int_operand" ""))]
+ 		  UNSPEC_ZAP)
+ 		(match_operand:DI 1 "reg_or_const_int_operand" "")))]
+   ""
+ {
+   if (GET_CODE (operands[2]) == CONST_INT)
+     {
+       rtx mask = alpha_expand_zap_mask (~ INTVAL (operands[2]));
+ 
+       if (operands[1] == const0_rtx)
+ 	{
+ 	  emit_move_insn (operands[0], const0_rtx);
+ 	  DONE;
+ 	}
+       if (operands[1] == constm1_rtx)
+ 	{
+ 	  emit_move_insn (operands[0], operands[1]);
+ 	  DONE;
+ 	}
+ 
+       operands[1] = force_reg (DImode, operands[1]);
+       emit_insn (gen_anddi3 (operands[0], operands[1], mask));
+       DONE;
+     }
+ 
+   operands[1] = force_reg (DImode, operands[1]);
+   operands[2] = gen_lowpart (QImode, operands[2]);
+ })
+ 
+ (define_insn "*builtin_zapnot_1"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(and:DI (unspec:DI
+                   [(not:QI (match_operand:QI 2 "register_operand" "r"))]
+                   UNSPEC_ZAP)
+ 		(match_operand:DI 1 "reg_or_0_operand" "rJ")))]
+   ""
+   "zapnot %r1,%2,%0"
+   [(set_attr "type" "shift")])
+ 
+ (define_insn "builtin_amask"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(unspec:DI [(match_operand:DI 1 "reg_or_8bit_operand" "rI")]
+ 		   UNSPEC_AMASK))]
+   ""
+   "amask %1,%0"
+   [(set_attr "type" "ilog")])
+ 
+ (define_insn "builtin_implver"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+   	(unspec:DI [(const_int 0)] UNSPEC_IMPLVER))]
+   ""
+   "implver %0"
+   [(set_attr "type" "ilog")])
+ 
+ (define_insn "builtin_rpcc"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+   	(unspec_volatile:DI [(const_int 0)] UNSPECV_RPCC))]
+   ""
+   "rpcc %0"
+   [(set_attr "type" "ilog")])
+ 
+ (define_expand "builtin_minub8"
+   [(match_operand:DI 0 "register_operand" "")
+    (match_operand:DI 1 "reg_or_0_operand" "")
+    (match_operand:DI 2 "reg_or_0_operand" "")]
+   "TARGET_MAX"
+ {
+   alpha_expand_builtin_vector_binop (gen_uminv8qi3, V8QImode, operands[0],
+ 				     operands[1], operands[2]);
+   DONE;
+ })
+ 
+ (define_expand "builtin_minsb8"
+   [(match_operand:DI 0 "register_operand" "")
+    (match_operand:DI 1 "reg_or_0_operand" "")
+    (match_operand:DI 2 "reg_or_0_operand" "")]
+   "TARGET_MAX"
+ {
+   alpha_expand_builtin_vector_binop (gen_sminv8qi3, V8QImode, operands[0],
+ 				     operands[1], operands[2]);
+   DONE;
+ })
+ 
+ (define_expand "builtin_minuw4"
+   [(match_operand:DI 0 "register_operand" "")
+    (match_operand:DI 1 "reg_or_0_operand" "")
+    (match_operand:DI 2 "reg_or_0_operand" "")]
+   "TARGET_MAX"
+ {
+   alpha_expand_builtin_vector_binop (gen_uminv4hi3, V4HImode, operands[0],
+ 				     operands[1], operands[2]);
+   DONE;
+ })
+ 
+ (define_expand "builtin_minsw4"
+   [(match_operand:DI 0 "register_operand" "")
+    (match_operand:DI 1 "reg_or_0_operand" "")
+    (match_operand:DI 2 "reg_or_0_operand" "")]
+   "TARGET_MAX"
+ {
+   alpha_expand_builtin_vector_binop (gen_sminv4hi3, V4HImode, operands[0],
+ 				     operands[1], operands[2]);
+   DONE;
+ })
+ 
+ (define_expand "builtin_maxub8"
+   [(match_operand:DI 0 "register_operand" "")
+    (match_operand:DI 1 "reg_or_0_operand" "")
+    (match_operand:DI 2 "reg_or_0_operand" "")]
+   "TARGET_MAX"
+ {
+   alpha_expand_builtin_vector_binop (gen_umaxv8qi3, V8QImode, operands[0],
+ 				     operands[1], operands[2]);
+   DONE;
+ })
+ 
+ (define_expand "builtin_maxsb8"
+   [(match_operand:DI 0 "register_operand" "")
+    (match_operand:DI 1 "reg_or_0_operand" "")
+    (match_operand:DI 2 "reg_or_0_operand" "")]
+   "TARGET_MAX"
+ {
+   alpha_expand_builtin_vector_binop (gen_smaxv8qi3, V8QImode, operands[0],
+ 				     operands[1], operands[2]);
+   DONE;
+ })
+ 
+ (define_expand "builtin_maxuw4"
+   [(match_operand:DI 0 "register_operand" "")
+    (match_operand:DI 1 "reg_or_0_operand" "")
+    (match_operand:DI 2 "reg_or_0_operand" "")]
+   "TARGET_MAX"
+ {
+   alpha_expand_builtin_vector_binop (gen_umaxv4hi3, V4HImode, operands[0],
+ 				     operands[1], operands[2]);
+   DONE;
+ })
+ 
+ (define_expand "builtin_maxsw4"
+   [(match_operand:DI 0 "register_operand" "")
+    (match_operand:DI 1 "reg_or_0_operand" "")
+    (match_operand:DI 2 "reg_or_0_operand" "")]
+   "TARGET_MAX"
+ {
+   alpha_expand_builtin_vector_binop (gen_smaxv4hi3, V4HImode, operands[0],
+ 				     operands[1], operands[2]);
+   DONE;
+ })
+ 
+ (define_insn "builtin_perr"
+   [(set (match_operand:DI 0 "register_operand" "=r")
+ 	(unspec:DI [(match_operand:DI 1 "reg_or_0_operand" "%rJ")
+ 		    (match_operand:DI 2 "reg_or_8bit_operand" "rJ")]
+ 		   UNSPEC_PERR))]
+   "TARGET_MAX"
+   "perr %r1,%r2,%0"
+   [(set_attr "type" "mvi")])
+ 
+ (define_expand "builtin_pklb"
+   [(set (match_operand:DI 0 "register_operand" "")
+ 	(vec_concat:V8QI
+ 	  (vec_concat:V4QI
+ 	    (truncate:V2QI (match_operand:DI 1 "register_operand" ""))
+ 	    (match_dup 2))
+ 	  (match_dup 3)))]
+   "TARGET_MAX"
+ {
+   operands[0] = gen_lowpart (V8QImode, operands[0]);
+   operands[1] = gen_lowpart (V2SImode, operands[1]);
+   operands[2] = CONST0_RTX (V2QImode);
+   operands[3] = CONST0_RTX (V4QImode);
+ })
+ 
+ (define_insn "*pklb"
+   [(set (match_operand:V8QI 0 "register_operand" "=r")
+ 	(vec_concat:V8QI
+ 	  (vec_concat:V4QI
+ 	    (truncate:V2QI (match_operand:V2SI 1 "register_operand" "r"))
+ 	    (match_operand:V2QI 2 "const0_operand" ""))
+ 	  (match_operand:V4QI 3 "const0_operand" "")))]
+   "TARGET_MAX"
+   "pklb %r1,%0"
+   [(set_attr "type" "mvi")])
+ 
+ (define_expand "builtin_pkwb"
+   [(set (match_operand:DI 0 "register_operand" "")
+ 	(vec_concat:V8QI
+ 	  (truncate:V4QI (match_operand:DI 1 "register_operand" ""))
+ 	  (match_dup 2)))]
+   "TARGET_MAX"
+ {
+   operands[0] = gen_lowpart (V8QImode, operands[0]);
+   operands[1] = gen_lowpart (V4HImode, operands[1]);
+   operands[2] = CONST0_RTX (V4QImode);
+ })
+ 
+ (define_insn "*pkwb"
+   [(set (match_operand:V8QI 0 "register_operand" "")
+ 	(vec_concat:V8QI
+ 	  (truncate:V4QI (match_operand:V4HI 1 "register_operand" ""))
+ 	  (match_operand:V4QI 2 "const0_operand" "")))]
+   "TARGET_MAX"
+   "pkwb %r1,%0"
+   [(set_attr "type" "mvi")])
+ 
+ (define_expand "builtin_unpkbl"
+   [(set (match_operand:DI 0 "register_operand" "")
+ 	(zero_extend:V2SI
+ 	  (vec_select:V2QI (match_operand:DI 1 "register_operand" "")
+ 			   (parallel [(const_int 0) (const_int 1)]))))]
+   "TARGET_MAX"
+ {
+   operands[0] = gen_lowpart (V2SImode, operands[0]);
+   operands[1] = gen_lowpart (V8QImode, operands[1]);
+ })
+ 
+ (define_insn "*unpkbl"
+   [(set (match_operand:V2SI 0 "register_operand" "=r")
+ 	(zero_extend:V2SI
+ 	  (vec_select:V2QI (match_operand:V8QI 1 "reg_or_0_operand" "rW")
+ 			   (parallel [(const_int 0) (const_int 1)]))))]
+   "TARGET_MAX"
+   "unpkbl %r1,%0"
+   [(set_attr "type" "mvi")])
+ 
+ (define_expand "builtin_unpkbw"
+   [(set (match_operand:DI 0 "register_operand" "")
+ 	(zero_extend:V4HI
+ 	  (vec_select:V4QI (match_operand:DI 1 "register_operand" "")
+ 			   (parallel [(const_int 0)
+ 				      (const_int 1)
+ 				      (const_int 2)
+ 				      (const_int 3)]))))]
+   "TARGET_MAX"
+ {
+   operands[0] = gen_lowpart (V4HImode, operands[0]);
+   operands[1] = gen_lowpart (V8QImode, operands[1]);
+ })
+ 
+ (define_insn "*unpkbw"
+   [(set (match_operand:V4HI 0 "register_operand" "=r")
+ 	(zero_extend:V4HI
+ 	  (vec_select:V4QI (match_operand:V8QI 1 "reg_or_0_operand" "rW")
+ 			   (parallel [(const_int 0)
+ 				      (const_int 1)
+ 				      (const_int 2)
+ 				      (const_int 3)]))))]
+   "TARGET_MAX"
+   "unpkbw %r1,%0"
+   [(set_attr "type" "mvi")])
+ 
  ;; The call patterns are at the end of the file because their
  ;; wildcard operand0 interferes with nice recognition.
  
Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.76
diff -c -p -d -r1.76 extend.texi
*** doc/extend.texi	30 May 2002 21:28:13 -0000	1.76
--- doc/extend.texi	4 Jun 2002 03:57:36 -0000
*************** to those machines.  Generally these gene
*** 4754,4762 ****
--- 4754,4804 ----
  instructions, but allow the compiler to schedule those calls.
  
  @menu
+ * Alpha Built-in Functions::
  * X86 Built-in Functions::
  * PowerPC AltiVec Built-in Functions::
  @end menu
+ 
+ @node Alpha Built-in Functions
+ @subsection Alpha Built-in Functions
+ 
+ These built-in functions are available for the Alpha family of
+ processors, depending on the command-line switches used.
+ 
+ The following built-in functions are always available.  They 
+ all generate the machine instruction that is part of the name.
+ 
+ @example
+ long __builtin_alpha_implver (void)
+ long __builtin_alpha_rpcc (void)
+ long __builtin_alpha_amask (long)
+ long __builtin_alpha_cmpbge (long, long)
+ long __builtin_alpha_extql (long, long)
+ long __builtin_alpha_extqh (long, long)
+ long __builtin_alpha_zap (long, long)
+ long __builtin_alpha_zapnot (long, long)
+ @end example
+ 
+ The following built-in functions are always with @option{-mmax}
+ or @option{-mcpu=@var{cpu}} where @var{cpu} is @code{pca56} or
+ later.  They all generate the machine instruction that is part
+ of the name.
+ 
+ @example
+ long __builtin_alpha_pklb (long)
+ long __builtin_alpha_pkwb (long)
+ long __builtin_alpha_unpkbl (long)
+ long __builtin_alpha_unpkbw (long)
+ long __builtin_alpha_minub8 (long, long)
+ long __builtin_alpha_minsb8 (long, long)
+ long __builtin_alpha_minuw4 (long, long)
+ long __builtin_alpha_minsw4 (long, long)
+ long __builtin_alpha_maxub8 (long, long)
+ long __builtin_alpha_maxsb8 (long, long)
+ long __builtin_alpha_maxuw4 (long, long)
+ long __builtin_alpha_maxsw4 (long, long)
+ long __builtin_alpha_perr (long, long)
+ @end example
  
  @node X86 Built-in Functions
  @subsection X86 Built-in Functions
Index: testsuite/gcc.dg/alpha-base-1.c
===================================================================
RCS file: testsuite/gcc.dg/alpha-base-1.c
diff -N testsuite/gcc.dg/alpha-base-1.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/alpha-base-1.c	4 Jun 2002 03:57:36 -0000
***************
*** 0 ****
--- 1,49 ----
+ /* Test that the base isa builtins compile.  */
+ /* { dg-do link { target alpha*-*-* } } */
+ /* { dg-options "-mcpu=ev4" } */
+ 
+ void test_BASE (long x, long y)
+ {
+   volatile long sink;
+   long z;
+ 
+   sink = __builtin_alpha_implver ();
+   sink = __builtin_alpha_rpcc ();
+ 
+   sink = __builtin_alpha_amask (-1);
+   sink = __builtin_alpha_amask (x);
+ 
+   sink = __builtin_alpha_cmpbge (x, y);
+   sink = __builtin_alpha_cmpbge (-1, x);
+   sink = __builtin_alpha_extql (x, y);
+   sink = __builtin_alpha_extqh (x, y);
+ }
+ 
+ void test_zap (long x, long y)
+ {
+   volatile long sink;
+   long z;
+   sink = __builtin_alpha_zap (x, y);
+   sink = __builtin_alpha_zap (x, 0xaa);
+   z = 0xaa;
+   sink = __builtin_alpha_zap (x, z);
+   z = 0;
+   sink = __builtin_alpha_zap (z, x);
+   sink = __builtin_alpha_zap (x, z);
+ }
+ 
+ void test_zapnot (long x, long y)
+ {
+   volatile long sink;
+   long z;
+ 
+   sink = __builtin_alpha_zapnot (x, y);
+   sink = __builtin_alpha_zapnot (x, 0xaa);
+   z = 0xaa;
+   sink = __builtin_alpha_zapnot (x, z);
+   z = 0;
+   sink = __builtin_alpha_zapnot (z, x);
+   sink = __builtin_alpha_zapnot (x, z);
+ }
+ 
+ int main() { return 0; }
Index: testsuite/gcc.dg/alpha-base-2.c
===================================================================
RCS file: testsuite/gcc.dg/alpha-base-2.c
diff -N testsuite/gcc.dg/alpha-base-2.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/alpha-base-2.c	4 Jun 2002 03:57:36 -0000
***************
*** 0 ****
--- 1,5 ----
+ /* Test that alpha-base-1.c compiles with optimization.  */
+ /* { dg-do link { target alpha*-*-* } } */
+ /* { dg-options "-mcpu=ev4 -O2" } */
+ 
+ #include "alpha-base-1.c"
Index: testsuite/gcc.dg/alpha-max-1.c
===================================================================
RCS file: testsuite/gcc.dg/alpha-max-1.c
diff -N testsuite/gcc.dg/alpha-max-1.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/alpha-max-1.c	4 Jun 2002 03:57:36 -0000
***************
*** 0 ****
--- 1,27 ----
+ /* Test that the MAX isa builtins compile.  */
+ /* { dg-do link { target alpha*-*-* } } */
+ /* { dg-options "-mmax" } */
+ 
+ void test_MAX (long x, long y)
+ {
+   volatile long sink;
+ 
+   sink = __builtin_alpha_pklb (x);
+   sink = __builtin_alpha_pkwb (x);
+   sink = __builtin_alpha_unpkbl (x);
+   sink = __builtin_alpha_unpkbw (x);
+ 
+   sink = __builtin_alpha_minub8 (0, x);
+   sink = __builtin_alpha_minub8 (1, x);
+   sink = __builtin_alpha_minub8 (x, y);
+   sink = __builtin_alpha_minsb8 (x, y);
+   sink = __builtin_alpha_minuw4 (x, y);
+   sink = __builtin_alpha_minsw4 (x, y);
+   sink = __builtin_alpha_maxub8 (x, y);
+   sink = __builtin_alpha_maxsb8 (x, y);
+   sink = __builtin_alpha_maxuw4 (x, y);
+   sink = __builtin_alpha_maxsw4 (x, y);
+   sink = __builtin_alpha_perr (x, y);
+ }
+ 
+ int main() { return 0; }
Index: testsuite/gcc.dg/alpha-max-2.c
===================================================================
RCS file: testsuite/gcc.dg/alpha-max-2.c
diff -N testsuite/gcc.dg/alpha-max-2.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/gcc.dg/alpha-max-2.c	4 Jun 2002 03:57:36 -0000
***************
*** 0 ****
--- 1,5 ----
+ /* Test that alpha-max-1.c compiles with optimization.  */
+ /* { dg-do link { target alpha*-*-* } } */
+ /* { dg-options "-mmax -O2" } */
+ 
+ #include "alpha-max-1.c"



More information about the Gcc-patches mailing list