static rtx altivec_expand_unop_builtin PARAMS ((enum insn_code, tree, rtx));
static rtx altivec_expand_binop_builtin PARAMS ((enum insn_code, tree, rtx));
static rtx altivec_expand_ternop_builtin PARAMS ((enum insn_code, tree, rtx));
+static rtx altivec_expand_stv_builtin PARAMS ((enum insn_code, tree));
static void rs6000_parse_abi_options PARAMS ((void));
static int first_altivec_reg_to_save PARAMS ((void));
static unsigned int compute_vrsave_mask PARAMS ((void));
return target;
}
+
+static rtx
+altivec_expand_stv_builtin (icode, arglist)
+ enum insn_code icode;
+ tree arglist;
+{
+ tree arg0 = TREE_VALUE (arglist);
+ tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ rtx op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+ rtx pat;
+ enum machine_mode mode0 = insn_data[icode].operand[0].mode;
+ enum machine_mode mode1 = insn_data[icode].operand[1].mode;
+ enum machine_mode mode2 = insn_data[icode].operand[2].mode;
+
+ /* Invalid arguments. Bail before doing anything stoopid! */
+ if (arg0 == error_mark_node
+ || arg1 == error_mark_node
+ || arg2 == error_mark_node)
+ return NULL_RTX;
+
+ if (! (*insn_data[icode].operand[2].predicate) (op0, mode2))
+ op0 = copy_to_mode_reg (mode2, op0);
+ if (! (*insn_data[icode].operand[0].predicate) (op1, mode0))
+ op1 = copy_to_mode_reg (mode0, op1);
+ if (! (*insn_data[icode].operand[1].predicate) (op2, mode1))
+ op2 = copy_to_mode_reg (mode1, op2);
+
+ pat = GEN_FCN (icode) (op1, op2, op0);
+ if (pat)
+ emit_insn (pat);
+ return NULL_RTX;
+}
+
static rtx
altivec_expand_ternop_builtin (icode, arglist, target)
enum insn_code icode;
emit_insn (pat);
return NULL_RTX;
+ case ALTIVEC_BUILTIN_STVX:
+ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvx, arglist);
+ case ALTIVEC_BUILTIN_STVEBX:
+ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvebx, arglist);
+ case ALTIVEC_BUILTIN_STVEHX:
+ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvehx, arglist);
+ case ALTIVEC_BUILTIN_STVEWX:
+ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvewx, arglist);
+ case ALTIVEC_BUILTIN_STVXL:
+ return altivec_expand_stv_builtin (CODE_FOR_altivec_stvxl, arglist);
+
case ALTIVEC_BUILTIN_MFVSCR:
icode = CODE_FOR_altivec_mfvscr;
tmode = insn_data[icode].operand[0].mode;
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);
+ /* LV* are funky. We initialized them differently. */
+ switch (fcode)
+ {
+ case ALTIVEC_BUILTIN_LVSL:
+ return altivec_expand_binop_builtin (CODE_FOR_altivec_lvsl,
+ arglist, target);
+ case ALTIVEC_BUILTIN_LVSR:
+ return altivec_expand_binop_builtin (CODE_FOR_altivec_lvsr,
+ arglist, target);
+ case ALTIVEC_BUILTIN_LVEBX:
+ return altivec_expand_binop_builtin (CODE_FOR_altivec_lvebx,
+ arglist, target);
+ case ALTIVEC_BUILTIN_LVEHX:
+ return altivec_expand_binop_builtin (CODE_FOR_altivec_lvehx,
+ arglist, target);
+ case ALTIVEC_BUILTIN_LVEWX:
+ return altivec_expand_binop_builtin (CODE_FOR_altivec_lvewx,
+ arglist, target);
+ case ALTIVEC_BUILTIN_LVXL:
+ return altivec_expand_binop_builtin (CODE_FOR_altivec_lvxl,
+ arglist, target);
+ case ALTIVEC_BUILTIN_LVX:
+ return altivec_expand_binop_builtin (CODE_FOR_altivec_lvx,
+ arglist, target);
+ default:
+ break;
+ /* Fall through. */
+ }
/* Handle simple ternary operations. */
d = (struct builtin_description *) bdesc_3arg;
tree_cons (NULL_TREE, V4SI_type_node,
endlink));
+ /* void foo (vint, int, void *). */
+ tree void_ftype_v4si_int_pvoid
+ = build_function_type (void_type_node,
+ tree_cons (NULL_TREE, V4SI_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE,
+ pvoid_type_node,
+ endlink))));
+
+ /* void foo (vchar, int, void *). */
+ tree void_ftype_v16qi_int_pvoid
+ = build_function_type (void_type_node,
+ tree_cons (NULL_TREE, V16QI_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE,
+ pvoid_type_node,
+ endlink))));
+
+ /* void foo (vshort, int, void *). */
+ tree void_ftype_v8hi_int_pvoid
+ = build_function_type (void_type_node,
+ tree_cons (NULL_TREE, V8HI_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE,
+ pvoid_type_node,
+ endlink))));
+
/* void foo (char). */
tree void_ftype_qi
= build_function_type (void_type_node,
tree_cons (NULL_TREE, pvoid_type_node,
endlink)));
+ tree v4si_ftype_int_pvoid
+ = build_function_type (V4SI_type_node,
+ tree_cons (NULL_TREE, integer_type_node,
+ tree_cons (NULL_TREE, pvoid_type_node,
+ endlink)));
+
+ tree v8hi_ftype_int_pvoid
+ = build_function_type (V8HI_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,
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);
-
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvebx", v16qi_ftype_int_pvoid, ALTIVEC_BUILTIN_LVEBX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvehx", v8hi_ftype_int_pvoid, ALTIVEC_BUILTIN_LVEHX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvewx", v4si_ftype_int_pvoid, ALTIVEC_BUILTIN_LVEWX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvxl", v4si_ftype_int_pvoid, ALTIVEC_BUILTIN_LVXL);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_lvx", v4si_ftype_int_pvoid, ALTIVEC_BUILTIN_LVX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvx", void_ftype_v4si_int_pvoid, ALTIVEC_BUILTIN_STVX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvebx", void_ftype_v16qi_int_pvoid, ALTIVEC_BUILTIN_STVEBX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvehx", void_ftype_v8hi_int_pvoid, ALTIVEC_BUILTIN_STVEHX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvewx", void_ftype_v4si_int_pvoid, ALTIVEC_BUILTIN_STVEWX);
+ def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvxl", void_ftype_v4si_int_pvoid, ALTIVEC_BUILTIN_STVXL);
+
/* Add the simple ternary operators. */
d = (struct builtin_description *) bdesc_3arg;
for (i = 0; i < sizeof (bdesc_3arg) / sizeof *d; i++, d++)
"TARGET_ALTIVEC"
"lvsr %0,%1,%2"
[(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvebx"
+ [(set (match_operand:V16QI 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")] 196))]
+ "TARGET_ALTIVEC"
+ "lvebx %0,%1,%2"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvehx"
+ [(set (match_operand:V8HI 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")] 197))]
+ "TARGET_ALTIVEC"
+ "lvehx %0,%1,%2"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvewx"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")] 198))]
+ "TARGET_ALTIVEC"
+ "lvewx %0,%1,%2"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvxl"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")] 199))]
+ "TARGET_ALTIVEC"
+ "lvxl %0,%1,%2"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_lvx"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:SI 1 "register_operand" "r")
+ (match_operand:SI 2 "register_operand" "r")] 200))]
+ "TARGET_ALTIVEC"
+ "lvx %0,%1,%2"
+ [(set_attr "type" "vecload")])
+
+(define_insn "altivec_stvx"
+ [(set (mem:V4SI
+ (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "register_operand" "r"))
+ (const_int -16)))
+ (match_operand:V4SI 2 "register_operand" "v"))]
+ "TARGET_ALTIVEC"
+ "stvx %2,%0,%1"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "altivec_stvxl"
+ [(parallel
+ [(set (mem:V4SI
+ (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "register_operand" "r"))
+ (const_int -16)))
+ (match_operand:V4SI 2 "register_operand" "v"))
+ (unspec [(const_int 0)] 201)])]
+ "TARGET_ALTIVEC"
+ "stvxl %2,%0,%1"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "altivec_stvebx"
+ [(parallel
+ [(set (mem:V16QI
+ (plus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "register_operand" "r")))
+ (match_operand:V16QI 2 "register_operand" "v"))
+ (unspec [(const_int 0)] 202)])]
+ "TARGET_ALTIVEC"
+ "stvebx %2,%0,%1"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "altivec_stvehx"
+ [(set (mem:V8HI
+ (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "register_operand" "r"))
+ (const_int -2)))
+ (match_operand:V8HI 2 "register_operand" "v"))]
+ "TARGET_ALTIVEC"
+ "stvehx %2,%0,%1"
+ [(set_attr "type" "vecstore")])
+
+(define_insn "altivec_stvewx"
+ [(set (mem:V4SI
+ (and:SI (plus:SI (match_operand:SI 0 "register_operand" "r")
+ (match_operand:SI 1 "register_operand" "r"))
+ (const_int -4)))
+ (match_operand:V4SI 2 "register_operand" "v"))]
+ "TARGET_ALTIVEC"
+ "stvewx %2,%0,%1"
+ [(set_attr "type" "vecstore")])