rs6000.c (altivec_expand_builtin): Add support for mtvscr, dssall, mfvscr, dss, lvsl...
authorAldy Hernandez <aldyh@redhat.com>
Thu, 10 Jan 2002 02:51:02 +0000 (02:51 +0000)
committerAldy Hernandez <aldyh@gcc.gnu.org>
Thu, 10 Jan 2002 02:51:02 +0000 (02:51 +0000)
* config/rs6000/rs6000.c (altivec_expand_builtin): Add support for
mtvscr, dssall, mfvscr, dss, lvsl, lvsr, dstt, dst, dstst, dststt.
(altivec_init_builtins): Same.
(altivec_expand_unop_builtin): Return NULL_RTX on error.
(altivec_expand_binop_builtin): Same.
(altivec_expand_ternop_builtin): Same.
(bdesc_dst): New.

* config/rs6000/rs6000.md ("altivec_mtvscr"): New.
("altivec_vctuxs"): Fix typo.
("altivec_vnmsubfp"): Same.
("altivec_dssall"): New.
("altivec_mfvscr"): New.
("altivec_dss"): New.
("altivec_lvsl"): New.
("altivec_lvsr"): New.
("altivec_dstt"): New.
("altivec_dstst"): New.
("altivec_dststt"): New.
("altivec_dst"): New.

* config/rs6000/rs6000.h (rs6000_builtins): Add mtvscr, dssall,
mfvscr, dss, lvsl, lvsr, dstt, dstst, dststt, dst.

From-SVN: r48708

gcc/ChangeLog
gcc/config/rs6000/rs6000.c
gcc/config/rs6000/rs6000.h
gcc/config/rs6000/rs6000.md

index 8909c4a58d5d6c5a170acfc01e55cccac0c19620..c30acc70ca5fd48c301bae83f0948f536939ad6e 100644 (file)
@@ -1,3 +1,32 @@
+2002-01-08  Aldy Hernandez  <aldyh@redhat.com>
+
+       * testuite/gcc.dg/altivec-4.c: Add test for mtvscr, dssall,
+       mfvscr, dss, lvsl, lvsr, dstt, dstst, dststt, dst.
+
+       * config/rs6000/rs6000.c (altivec_expand_builtin): Add support for
+       mtvscr, dssall, mfvscr, dss, lvsl, lvsr, dstt, dst, dstst, dststt.
+       (altivec_init_builtins): Same.
+       (altivec_expand_unop_builtin): Return NULL_RTX on error.
+       (altivec_expand_binop_builtin): Same.
+       (altivec_expand_ternop_builtin): Same.
+       (bdesc_dst): New.
+
+       * config/rs6000/rs6000.md ("altivec_mtvscr"): New.
+       ("altivec_vctuxs"): Fix typo.
+       ("altivec_vnmsubfp"): Same.
+       ("altivec_dssall"): New.
+       ("altivec_mfvscr"): New.
+       ("altivec_dss"): New.
+       ("altivec_lvsl"): New.
+       ("altivec_lvsr"): New.
+       ("altivec_dstt"): New.
+       ("altivec_dstst"): New.
+       ("altivec_dststt"): New.
+       ("altivec_dst"): New.
+
+       * config/rs6000/rs6000.h (rs6000_builtins): Add mtvscr, dssall,
+       mfvscr, dss, lvsl, lvsr, dstt, dstst, dststt, dst.
+
 2002-01-09  Richard Henderson  <rth@redhat.com>
 
        * config/alpha/alpha.md (prologue_mcount): Remove lituse_jsr reloc.
index 6466bb2c4f1392d1439fe43f172d4f459510e70f..b8b0453bfb2be0a8ee7f94520cc3bee6d06cbf98 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines used for code generation on IBM RS/6000.
    Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 
-   2000, 2001 Free Software Foundation, Inc.
+   2000, 2001, 2002 Free Software Foundation, Inc.
    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
 
 This file is part of GNU CC.
@@ -3240,6 +3240,16 @@ static const struct builtin_description bdesc_3arg[] =
   { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_4sf, "__builtin_altivec_vsldoi_4sf", ALTIVEC_BUILTIN_VSLDOI_4SF },
 };
 
+/* DST operations: void foo (void *, const int, const char).  */
+
+static const struct builtin_description bdesc_dst[] =
+{
+  { MASK_ALTIVEC, CODE_FOR_altivec_dst, "__builtin_altivec_dst", ALTIVEC_BUILTIN_DST },
+  { MASK_ALTIVEC, CODE_FOR_altivec_dstt, "__builtin_altivec_dstt", ALTIVEC_BUILTIN_DSTT },
+  { MASK_ALTIVEC, CODE_FOR_altivec_dstst, "__builtin_altivec_dstst", ALTIVEC_BUILTIN_DSTST },
+  { MASK_ALTIVEC, CODE_FOR_altivec_dststt, "__builtin_altivec_dststt", ALTIVEC_BUILTIN_DSTSTT }
+};
+
 /* Simple binary operations: VECc = foo (VECa, VECb).  */
 
 static const struct builtin_description bdesc_2arg[] =
@@ -3410,7 +3420,7 @@ altivec_expand_unop_builtin (icode, arglist, target)
 
   /* If we got invalid arguments bail out before generating bad rtl.  */
   if (arg0 == error_mark_node)
-    return target;
+    return NULL_RTX;
 
   if (target == 0
       || GET_MODE (target) != tmode
@@ -3444,7 +3454,7 @@ altivec_expand_binop_builtin (icode, arglist, target)
 
   /* If we got invalid arguments bail out before generating bad rtl.  */
   if (arg0 == error_mark_node || arg1 == error_mark_node)
-    return target;
+    return NULL_RTX;
 
   if (target == 0
       || GET_MODE (target) != tmode
@@ -3485,7 +3495,7 @@ altivec_expand_ternop_builtin (icode, arglist, target)
   if (arg0 == error_mark_node
       || arg1 == error_mark_node
       || arg2 == error_mark_node)
-    return target;
+    return NULL_RTX;
 
   if (target == 0
       || GET_MODE (target) != tmode
@@ -3516,9 +3526,9 @@ altivec_expand_builtin (exp, target)
   enum insn_code icode;
   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
   tree arglist = TREE_OPERAND (exp, 1);
-  tree arg0, arg1;
-  rtx op0, op1, pat;
-  enum machine_mode tmode, mode0, mode1;
+  tree arg0, arg1, arg2;
+  rtx op0, op1, op2, pat;
+  enum machine_mode tmode, mode0, mode1, mode2;
   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
   
   switch (fcode)
@@ -3622,9 +3632,8 @@ altivec_expand_builtin (exp, target)
        op1 = copy_to_mode_reg (mode1, op1);
 
       pat = GEN_FCN (icode) (op0, op1);
-      if (! pat)
-       return 0;
-      emit_insn (pat);
+      if (pat)
+       emit_insn (pat);
       return NULL_RTX;
 
     case ALTIVEC_BUILTIN_ST_INTERNAL_8hi:
@@ -3642,9 +3651,8 @@ altivec_expand_builtin (exp, target)
        op1 = copy_to_mode_reg (mode1, op1);
 
       pat = GEN_FCN (icode) (op0, op1);
-      if (! pat)
-       return 0;
-      emit_insn (pat);
+      if (pat)
+       emit_insn (pat);
       return NULL_RTX;
 
     case ALTIVEC_BUILTIN_ST_INTERNAL_4si:
@@ -3662,9 +3670,8 @@ altivec_expand_builtin (exp, target)
        op1 = copy_to_mode_reg (mode1, op1);
 
       pat = GEN_FCN (icode) (op0, op1);
-      if (! pat)
-       return 0;
-      emit_insn (pat);
+      if (pat)
+       emit_insn (pat);
       return NULL_RTX;
 
     case ALTIVEC_BUILTIN_ST_INTERNAL_4sf:
@@ -3682,12 +3689,103 @@ altivec_expand_builtin (exp, target)
        op1 = copy_to_mode_reg (mode1, op1);
 
       pat = GEN_FCN (icode) (op0, op1);
+      if (pat)
+       emit_insn (pat);
+      return NULL_RTX;
+
+    case ALTIVEC_BUILTIN_MFVSCR:
+      icode = CODE_FOR_altivec_mfvscr;
+      tmode = insn_data[icode].operand[0].mode;
+
+      if (target == 0
+         || GET_MODE (target) != tmode
+         || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+       target = gen_reg_rtx (tmode);
+      
+      pat = GEN_FCN (icode) (target);
       if (! pat)
        return 0;
       emit_insn (pat);
+      return target;
+
+    case ALTIVEC_BUILTIN_MTVSCR:
+      icode = CODE_FOR_altivec_mtvscr;
+      arg0 = TREE_VALUE (arglist);
+      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+      mode0 = insn_data[icode].operand[0].mode;
+
+      /* If we got invalid arguments bail out before generating bad rtl.  */
+      if (arg0 == error_mark_node)
+       return NULL_RTX;
+
+      if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
+       op0 = copy_to_mode_reg (mode0, op0);
+
+      pat = GEN_FCN (icode) (op0);
+      if (pat)
+       emit_insn (pat);
+      return NULL_RTX;
+      
+    case ALTIVEC_BUILTIN_DSSALL:
+      emit_insn (gen_altivec_dssall ());
+      return NULL_RTX;
+
+    case ALTIVEC_BUILTIN_DSS:
+      icode = CODE_FOR_altivec_dss;
+      arg0 = TREE_VALUE (arglist);
+      op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+      mode0 = insn_data[icode].operand[0].mode;
+
+      /* If we got invalid arguments bail out before generating bad rtl.  */
+      if (arg0 == error_mark_node)
+       return NULL_RTX;
+
+      if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
+       op0 = copy_to_mode_reg (mode0, op0);
+
+      emit_insn (gen_altivec_dss (op0));
       return NULL_RTX;
     }
 
+  /* Handle DST variants.  */
+  d = (struct builtin_description *) bdesc_dst;
+  for (i = 0; i < sizeof (bdesc_dst) / sizeof *d; i++, d++)
+    if (d->code == fcode)
+      {
+       arg0 = TREE_VALUE (arglist);
+       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+       arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+       op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+       op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+       mode0 = insn_data[d->icode].operand[0].mode;
+       mode1 = insn_data[d->icode].operand[1].mode;
+       mode2 = insn_data[d->icode].operand[2].mode;
+
+       /* Invalid arguments, bail out before generating bad rtl.  */
+       if (arg0 == error_mark_node
+           || arg1 == error_mark_node
+           || arg2 == error_mark_node)
+         return NULL_RTX;
+
+       if (! (*insn_data[d->icode].operand[0].predicate) (op0, mode0))
+         op0 = copy_to_mode_reg (mode0, op0);
+       if (! (*insn_data[d->icode].operand[1].predicate) (op1, mode1))
+         op1 = copy_to_mode_reg (mode1, op1);
+
+       if (GET_CODE (op2) != CONST_INT || INTVAL (op2) > 3)
+         {
+           error ("argument 3 of `%s' must be a 2-bit literal", d->name);
+           return NULL_RTX;
+         }
+
+       pat = GEN_FCN (d->icode) (op0, op1, op2);
+       if (pat != 0)
+         emit_insn (pat);
+
+       return NULL_RTX;
+      }
+
   /* Handle simple unary operations.  */
   d = (struct builtin_description *) bdesc_1arg;
   for (i = 0; i < sizeof (bdesc_1arg) / sizeof *d; i++, d++)
@@ -3700,6 +3798,14 @@ altivec_expand_builtin (exp, target)
     if (d->code == fcode)
       return altivec_expand_binop_builtin (d->icode, arglist, target);
 
+  /* LVS* are funky.  We initialized them differently.  */
+  if (fcode == ALTIVEC_BUILTIN_LVSL)
+    return altivec_expand_binop_builtin (CODE_FOR_altivec_lvsl,
+                                        arglist, target);
+  if (fcode == ALTIVEC_BUILTIN_LVSR)
+    return altivec_expand_binop_builtin (CODE_FOR_altivec_lvsr,
+                                        arglist, target);
+
   /* Handle simple ternary operations.  */
   d = (struct builtin_description *) bdesc_3arg;
   for (i = 0; i < sizeof  (bdesc_3arg) / sizeof *d; i++, d++)
@@ -3746,6 +3852,7 @@ altivec_init_builtins (void)
   tree endlink = void_list_node;
 
   tree pint_type_node = build_pointer_type (integer_type_node);
+  tree pvoid_type_node = build_pointer_type (void_type_node);
   tree pshort_type_node = build_pointer_type (short_integer_type_node);
   tree pchar_type_node = build_pointer_type (char_type_node);
   tree pfloat_type_node = build_pointer_type (float_type_node);
@@ -3820,6 +3927,15 @@ altivec_init_builtins (void)
     = build_function_type (V8HI_type_node,
                           tree_cons (NULL_TREE, V16QI_type_node, endlink));
 
+  /* void foo (void *, int, char/literal).  */
+  tree void_ftype_pvoid_int_char
+    = build_function_type (void_type_node,
+                          tree_cons (NULL_TREE, pvoid_type_node,
+                                     tree_cons (NULL_TREE, integer_type_node,
+                                                tree_cons (NULL_TREE,
+                                                           char_type_node,
+                                                           endlink))));
+
   /* void foo (int *, V4SI).  */
   tree void_ftype_pint_v4si
     = build_function_type (void_type_node,
@@ -3845,6 +3961,30 @@ altivec_init_builtins (void)
                                      tree_cons (NULL_TREE, V4SF_type_node,
                                                 endlink)));
 
+  /* void foo (V4SI).  */
+  tree void_ftype_v4si
+    = build_function_type (void_type_node,
+                          tree_cons (NULL_TREE, V4SI_type_node,
+                                     endlink));
+
+  /* void foo (char).  */
+  tree void_ftype_qi
+    = build_function_type (void_type_node,
+                          tree_cons (NULL_TREE, char_type_node,
+                                     endlink));
+
+  /* void foo (void).  */
+  tree void_ftype_void
+    = build_function_type (void_type_node,
+                          tree_cons (NULL_TREE, void_type_node,
+                                     endlink));
+
+  /* vshort foo (void).  */
+  tree v8hi_ftype_void
+    = build_function_type (V8HI_type_node,
+                          tree_cons (NULL_TREE, void_type_node,
+                                     endlink));
+
   tree v4si_ftype_v4si_v4si
     = build_function_type (V4SI_type_node,
                           tree_cons (NULL_TREE, V4SI_type_node,
@@ -4045,6 +4185,12 @@ altivec_init_builtins (void)
                                      tree_cons (NULL_TREE, V16QI_type_node,
                                                 endlink)));
 
+  tree v16qi_ftype_int_pvoid
+    = build_function_type (V16QI_type_node,
+                          tree_cons (NULL_TREE, integer_type_node,
+                                     tree_cons (NULL_TREE, pvoid_type_node,
+                                                endlink)));
+
   tree int_ftype_v8hi_v8hi
     = build_function_type (integer_type_node,
                           tree_cons (NULL_TREE, V8HI_type_node,
@@ -4059,6 +4205,12 @@ altivec_init_builtins (void)
   def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_8hi", void_ftype_pshort_v8hi, ALTIVEC_BUILTIN_ST_INTERNAL_8hi);
   def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_16qi", v16qi_ftype_pchar, ALTIVEC_BUILTIN_LD_INTERNAL_16qi);
   def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_16qi", void_ftype_pchar_v16qi, ALTIVEC_BUILTIN_ST_INTERNAL_16qi);
+  def_builtin (MASK_ALTIVEC, "__builtin_altivec_mtvscr", void_ftype_v4si, ALTIVEC_BUILTIN_MTVSCR);
+  def_builtin (MASK_ALTIVEC, "__builtin_altivec_mfvscr", v8hi_ftype_void, ALTIVEC_BUILTIN_MFVSCR);
+  def_builtin (MASK_ALTIVEC, "__builtin_altivec_dssall", void_ftype_void, ALTIVEC_BUILTIN_DSSALL);
+  def_builtin (MASK_ALTIVEC, "__builtin_altivec_dss", void_ftype_qi, ALTIVEC_BUILTIN_DSS);
+  def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsl", v16qi_ftype_int_pvoid, ALTIVEC_BUILTIN_LVSL);
+  def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvsr", v16qi_ftype_int_pvoid, ALTIVEC_BUILTIN_LVSR);
 
   /* Add the simple ternary operators.  */
   d = (struct builtin_description *) bdesc_3arg;
@@ -4153,6 +4305,11 @@ altivec_init_builtins (void)
       def_builtin (d->mask, d->name, type, d->code);
     }
 
+  /* Add the DST variants.  */
+  d = (struct builtin_description *) bdesc_dst;
+  for (i = 0; i < sizeof (bdesc_dst) / sizeof *d; i++, d++)
+    def_builtin (d->mask, d->name, void_ftype_pvoid_int_char, d->code);
+
   /* Add the simple binary operators.  */
   d = (struct builtin_description *) bdesc_2arg;
   for (i = 0; i < sizeof (bdesc_2arg) / sizeof *d; i++, d++)
index 854ab9b60629b573119ef6a751d56e9f731b24cd..36e9e9900b3d1fb0709060c0cf3e8d857e186e97 100644 (file)
@@ -2967,5 +2967,15 @@ enum rs6000_builtins
   ALTIVEC_BUILTIN_VCMPGTSW_P,
   ALTIVEC_BUILTIN_VCMPGTUB_P,
   ALTIVEC_BUILTIN_VCMPGTUH_P,
-  ALTIVEC_BUILTIN_VCMPGTUW_P
+  ALTIVEC_BUILTIN_VCMPGTUW_P,
+  ALTIVEC_BUILTIN_MTVSCR,
+  ALTIVEC_BUILTIN_MFVSCR,
+  ALTIVEC_BUILTIN_DSSALL,
+  ALTIVEC_BUILTIN_DSS,
+  ALTIVEC_BUILTIN_LVSL,
+  ALTIVEC_BUILTIN_LVSR,
+  ALTIVEC_BUILTIN_DSTT,
+  ALTIVEC_BUILTIN_DSTST,
+  ALTIVEC_BUILTIN_DSTSTT,
+  ALTIVEC_BUILTIN_DST
 };
index 84880eaf11aacbc3d1fd074417eab6747586fcf5..364a7e7dc90dd79dd8a65cfebb9021cebec394a3 100644 (file)
                               (match_operand:V4SF 2 "register_operand" "v"))
                    (match_operand:V4SF 3 "register_operand" "v")))]
   "TARGET_ALTIVEC"
-  "vmmsubfp %0,%1,%2,%3"
+  "vnmsubfp %0,%1,%2,%3"
   [(set_attr "type" "vecfloat")])
 
 
         (unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
                       (match_operand:QI 2 "immediate_operand" "i")] 153))]
   "TARGET_ALTIVEC"
-  "vctusx %0, %1, %2"
+  "vctuxs %0, %1, %2"
   [(set_attr "type" "vecfloat")])
 
 (define_insn "altivec_vctsxs"
                       (match_operand:V8HI 2 "register_operand" "v")] 185))]
   "TARGET_ALTIVEC"
   "vcmpgtsh. %0,%1,%2"
-[(set_attr "type" "veccmp")])
+  [(set_attr "type" "veccmp")])
+
+(define_insn "altivec_mtvscr"
+  [(unspec [(match_operand:V4SI 0 "register_operand" "v")] 186)]
+  "TARGET_ALTIVEC"
+  "mtvscr %0"
+  [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_mfvscr"
+  [(set (match_operand:V8HI 0 "register_operand" "=v")
+       (unspec:V8HI [(const_int 0)] 187))]
+  "TARGET_ALTIVEC"
+  "mfvscr %0"
+  [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_dssall"
+  [(unspec [(const_int 0)] 188)]
+  "TARGET_ALTIVEC"
+  "dssall"
+  [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_dss"
+  [(unspec [(match_operand:QI 0 "immediate_operand" "i")] 189)]
+  "TARGET_ALTIVEC"
+  "dss %0"
+  [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_dst"
+  [(unspec [(match_operand:SI 0 "register_operand" "b")
+           (match_operand:SI 1 "register_operand" "r")
+           (match_operand:QI 2 "immediate_operand" "i")] 190)]
+  "TARGET_ALTIVEC"
+  "dst %0,%1,%2"
+  [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_dstt"
+  [(unspec [(match_operand:SI 0 "register_operand" "b")
+           (match_operand:SI 1 "register_operand" "r")
+           (match_operand:QI 2 "immediate_operand" "i")] 191)]
+  "TARGET_ALTIVEC"
+  "dstt %0,%1,%2"
+  [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_dstst"
+  [(unspec [(match_operand:SI 0 "register_operand" "b")
+           (match_operand:SI 1 "register_operand" "r")
+           (match_operand:QI 2 "immediate_operand" "i")] 192)]
+  "TARGET_ALTIVEC"
+  "dstst %0,%1,%2"
+  [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_dststt"
+  [(unspec [(match_operand:SI 0 "register_operand" "b")
+           (match_operand:SI 1 "register_operand" "r")
+           (match_operand:QI 2 "immediate_operand" "i")] 193)]
+  "TARGET_ALTIVEC"
+  "dststt %0,%1,%2"
+  [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_lvsl"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+       (unspec:V16QI [(match_operand:SI 1 "register_operand" "r")
+                      (match_operand:SI 2 "register_operand" "r")] 194))]
+  "TARGET_ALTIVEC"
+  "lvsl %0,%1,%2"
+  [(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvsr"
+  [(set (match_operand:V16QI 0 "register_operand" "=v")
+       (unspec:V16QI [(match_operand:SI 1 "register_operand" "r")
+                      (match_operand:SI 2 "register_operand" "r")] 195))]
+  "TARGET_ALTIVEC"
+  "lvsr %0,%1,%2"
+  [(set_attr "type" "vecload")])