sh.c (sh_builtin_saveregs): Use get_varargs_alias_set.
* sh.c (sh_builtin_saveregs): Use get_varargs_alias_set. (sh_build_va_list, sh_va_start, sh_va_arg): New. * sh.h (BUILD_VA_LIST_TYPE): New. (EXPAND_BUILTIN_VA_START, EXPAND_BUILTIN_VA_ARG): New. From-SVN: r29415
This commit is contained in:
parent
5d3f2bd523
commit
514066a133
|
@ -3889,7 +3889,7 @@ sh_builtin_saveregs ()
|
||||||
int n_floatregs = MAX (0, NPARM_REGS (SFmode) - first_floatreg);
|
int n_floatregs = MAX (0, NPARM_REGS (SFmode) - first_floatreg);
|
||||||
int ptrsize = GET_MODE_SIZE (Pmode);
|
int ptrsize = GET_MODE_SIZE (Pmode);
|
||||||
rtx valist, regbuf, fpregs;
|
rtx valist, regbuf, fpregs;
|
||||||
int bufsize, regno;
|
int bufsize, regno, alias_set;
|
||||||
|
|
||||||
/* Allocate block of memory for the regs. */
|
/* Allocate block of memory for the regs. */
|
||||||
/* ??? If n_intregs + n_floatregs == 0, should we allocate at least 1 byte?
|
/* ??? If n_intregs + n_floatregs == 0, should we allocate at least 1 byte?
|
||||||
|
@ -3897,17 +3897,18 @@ sh_builtin_saveregs ()
|
||||||
bufsize = (n_intregs * UNITS_PER_WORD) + (n_floatregs * UNITS_PER_WORD);
|
bufsize = (n_intregs * UNITS_PER_WORD) + (n_floatregs * UNITS_PER_WORD);
|
||||||
|
|
||||||
regbuf = assign_stack_local (BLKmode, bufsize, 0);
|
regbuf = assign_stack_local (BLKmode, bufsize, 0);
|
||||||
MEM_SET_IN_STRUCT_P (regbuf, 1);
|
alias_set = get_varargs_alias_set ();
|
||||||
|
MEM_ALIAS_SET (regbuf) = alias_set;
|
||||||
|
|
||||||
/* Save int args.
|
/* Save int args.
|
||||||
This is optimized to only save the regs that are necessary. Explicitly
|
This is optimized to only save the regs that are necessary. Explicitly
|
||||||
named args need not be saved. */
|
named args need not be saved. */
|
||||||
if (n_intregs > 0)
|
if (n_intregs > 0)
|
||||||
move_block_from_reg (BASE_ARG_REG (SImode) + first_intreg,
|
move_block_from_reg (BASE_ARG_REG (SImode) + first_intreg,
|
||||||
gen_rtx_MEM (BLKmode,
|
change_address (regbuf, BLKmode,
|
||||||
plus_constant (XEXP (regbuf, 0),
|
plus_constant (XEXP (regbuf, 0),
|
||||||
(n_floatregs
|
(n_floatregs
|
||||||
* UNITS_PER_WORD))),
|
* UNITS_PER_WORD))),
|
||||||
n_intregs, n_intregs * UNITS_PER_WORD);
|
n_intregs, n_intregs * UNITS_PER_WORD);
|
||||||
|
|
||||||
/* Save float args.
|
/* Save float args.
|
||||||
|
@ -3924,18 +3925,23 @@ sh_builtin_saveregs ()
|
||||||
GEN_INT (n_floatregs * UNITS_PER_WORD)));
|
GEN_INT (n_floatregs * UNITS_PER_WORD)));
|
||||||
if (TARGET_SH4)
|
if (TARGET_SH4)
|
||||||
{
|
{
|
||||||
|
rtx mem;
|
||||||
for (regno = NPARM_REGS (DFmode) - 2; regno >= first_floatreg; regno -= 2)
|
for (regno = NPARM_REGS (DFmode) - 2; regno >= first_floatreg; regno -= 2)
|
||||||
{
|
{
|
||||||
emit_insn (gen_addsi3 (fpregs, fpregs,
|
emit_insn (gen_addsi3 (fpregs, fpregs,
|
||||||
GEN_INT (-2 * UNITS_PER_WORD)));
|
GEN_INT (-2 * UNITS_PER_WORD)));
|
||||||
emit_move_insn (gen_rtx (MEM, DFmode, fpregs),
|
mem = gen_rtx_MEM (DFmode, fpregs);
|
||||||
|
MEM_ALIAS_SET (mem) = alias_set;
|
||||||
|
emit_move_insn (mem,
|
||||||
gen_rtx (REG, DFmode, BASE_ARG_REG (DFmode) + regno));
|
gen_rtx (REG, DFmode, BASE_ARG_REG (DFmode) + regno));
|
||||||
}
|
}
|
||||||
regno = first_floatreg;
|
regno = first_floatreg;
|
||||||
if (regno & 1)
|
if (regno & 1)
|
||||||
{
|
{
|
||||||
emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (- UNITS_PER_WORD)));
|
emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (- UNITS_PER_WORD)));
|
||||||
emit_move_insn (gen_rtx (MEM, SFmode, fpregs),
|
mem = gen_rtx_MEM (SFmode, fpregs);
|
||||||
|
MEM_ALIAS_SET (mem) = alias_set;
|
||||||
|
emit_move_insn (mem,
|
||||||
gen_rtx (REG, SFmode, BASE_ARG_REG (SFmode) + regno
|
gen_rtx (REG, SFmode, BASE_ARG_REG (SFmode) + regno
|
||||||
- (TARGET_LITTLE_ENDIAN != 0)));
|
- (TARGET_LITTLE_ENDIAN != 0)));
|
||||||
}
|
}
|
||||||
|
@ -3943,8 +3949,11 @@ sh_builtin_saveregs ()
|
||||||
else
|
else
|
||||||
for (regno = NPARM_REGS (SFmode) - 1; regno >= first_floatreg; regno--)
|
for (regno = NPARM_REGS (SFmode) - 1; regno >= first_floatreg; regno--)
|
||||||
{
|
{
|
||||||
|
rtx mem;
|
||||||
emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (- UNITS_PER_WORD)));
|
emit_insn (gen_addsi3 (fpregs, fpregs, GEN_INT (- UNITS_PER_WORD)));
|
||||||
emit_move_insn (gen_rtx_MEM (SFmode, fpregs),
|
mem = gen_rtx_MEM (SFmode, fpregs);
|
||||||
|
MEM_ALIAS_SET (mem) = alias_set;
|
||||||
|
emit_move_insn (mem,
|
||||||
gen_rtx_REG (SFmode, BASE_ARG_REG (SFmode) + regno));
|
gen_rtx_REG (SFmode, BASE_ARG_REG (SFmode) + regno));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3952,6 +3961,256 @@ sh_builtin_saveregs ()
|
||||||
return XEXP (regbuf, 0);
|
return XEXP (regbuf, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Define the `__builtin_va_list' type for the ABI. */
|
||||||
|
|
||||||
|
tree
|
||||||
|
sh_build_va_list ()
|
||||||
|
{
|
||||||
|
tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
|
||||||
|
tree record;
|
||||||
|
|
||||||
|
if ((! TARGET_SH3E && ! TARGET_SH4) || TARGET_HITACHI)
|
||||||
|
return ptr_type_node;
|
||||||
|
|
||||||
|
record = make_node (RECORD_TYPE);
|
||||||
|
|
||||||
|
f_next_o = build_decl (FIELD_DECL, get_identifier ("__va_next_o"),
|
||||||
|
ptr_type_node);
|
||||||
|
f_next_o_limit = build_decl (FIELD_DECL,
|
||||||
|
get_identifier ("__va_next_o_limit"),
|
||||||
|
ptr_type_node);
|
||||||
|
f_next_fp = build_decl (FIELD_DECL, get_identifier ("__va_next_fp"),
|
||||||
|
ptr_type_node);
|
||||||
|
f_next_fp_limit = build_decl (FIELD_DECL,
|
||||||
|
get_identifier ("__va_next_fp_limit"),
|
||||||
|
ptr_type_node);
|
||||||
|
f_next_stack = build_decl (FIELD_DECL, get_identifier ("__va_next_stack"),
|
||||||
|
ptr_type_node);
|
||||||
|
|
||||||
|
DECL_FIELD_CONTEXT (f_next_o) = record;
|
||||||
|
DECL_FIELD_CONTEXT (f_next_o_limit) = record;
|
||||||
|
DECL_FIELD_CONTEXT (f_next_fp) = record;
|
||||||
|
DECL_FIELD_CONTEXT (f_next_fp_limit) = record;
|
||||||
|
DECL_FIELD_CONTEXT (f_next_stack) = record;
|
||||||
|
|
||||||
|
TYPE_FIELDS (record) = f_next_o;
|
||||||
|
TREE_CHAIN (f_next_o) = f_next_o_limit;
|
||||||
|
TREE_CHAIN (f_next_o_limit) = f_next_fp;
|
||||||
|
TREE_CHAIN (f_next_fp) = f_next_fp_limit;
|
||||||
|
TREE_CHAIN (f_next_fp_limit) = f_next_stack;
|
||||||
|
|
||||||
|
layout_type (record);
|
||||||
|
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Implement `va_start' for varargs and stdarg. */
|
||||||
|
|
||||||
|
void
|
||||||
|
sh_va_start (stdarg_p, valist, nextarg)
|
||||||
|
int stdarg_p;
|
||||||
|
tree valist;
|
||||||
|
rtx nextarg;
|
||||||
|
{
|
||||||
|
tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
|
||||||
|
tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack;
|
||||||
|
tree t, u;
|
||||||
|
int nfp, nint;
|
||||||
|
|
||||||
|
if ((! TARGET_SH3E && ! TARGET_SH4) || TARGET_HITACHI)
|
||||||
|
{
|
||||||
|
std_expand_builtin_va_start (stdarg_p, valist, nextarg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_next_o = TYPE_FIELDS (va_list_type_node);
|
||||||
|
f_next_o_limit = TREE_CHAIN (f_next_o);
|
||||||
|
f_next_fp = TREE_CHAIN (f_next_o_limit);
|
||||||
|
f_next_fp_limit = TREE_CHAIN (f_next_fp);
|
||||||
|
f_next_stack = TREE_CHAIN (f_next_fp_limit);
|
||||||
|
|
||||||
|
next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o);
|
||||||
|
next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
|
||||||
|
valist, f_next_o_limit);
|
||||||
|
next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp), valist, f_next_fp);
|
||||||
|
next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
|
||||||
|
valist, f_next_fp_limit);
|
||||||
|
next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack),
|
||||||
|
valist, f_next_stack);
|
||||||
|
|
||||||
|
/* Call __builtin_saveregs. */
|
||||||
|
u = make_tree (ptr_type_node, expand_builtin_saveregs ());
|
||||||
|
t = build (MODIFY_EXPR, ptr_type_node, next_fp, u);
|
||||||
|
TREE_SIDE_EFFECTS (t) = 1;
|
||||||
|
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||||
|
|
||||||
|
nfp = current_function_args_info.arg_count[SH_ARG_FLOAT];
|
||||||
|
if (nfp < 8)
|
||||||
|
nfp = 8 - nfp;
|
||||||
|
else
|
||||||
|
nfp = 0;
|
||||||
|
u = fold (build (PLUS_EXPR, ptr_type_node, u,
|
||||||
|
build_int_2 (UNITS_PER_WORD * nfp, 0)));
|
||||||
|
t = build (MODIFY_EXPR, ptr_type_node, next_fp_limit, u);
|
||||||
|
TREE_SIDE_EFFECTS (t) = 1;
|
||||||
|
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||||
|
|
||||||
|
t = build (MODIFY_EXPR, ptr_type_node, next_o, u);
|
||||||
|
TREE_SIDE_EFFECTS (t) = 1;
|
||||||
|
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||||
|
|
||||||
|
nint = current_function_args_info.arg_count[SH_ARG_INT];
|
||||||
|
if (nint < 4)
|
||||||
|
nint = 4 - nint;
|
||||||
|
else
|
||||||
|
nint = 0;
|
||||||
|
u = fold (build (PLUS_EXPR, ptr_type_node, u,
|
||||||
|
build_int_2 (UNITS_PER_WORD * nint, 0)));
|
||||||
|
t = build (MODIFY_EXPR, ptr_type_node, next_o_limit, u);
|
||||||
|
TREE_SIDE_EFFECTS (t) = 1;
|
||||||
|
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||||
|
|
||||||
|
u = make_tree (ptr_type_node, nextarg);
|
||||||
|
if (! stdarg_p && (nint == 0 || nfp == 0))
|
||||||
|
{
|
||||||
|
u = fold (build (PLUS_EXPR, ptr_type_node, u,
|
||||||
|
build_int_2 (-UNITS_PER_WORD, -1)));
|
||||||
|
}
|
||||||
|
t = build (MODIFY_EXPR, ptr_type_node, next_stack, u);
|
||||||
|
TREE_SIDE_EFFECTS (t) = 1;
|
||||||
|
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Implement `va_arg'. */
|
||||||
|
|
||||||
|
rtx
|
||||||
|
sh_va_arg (valist, type)
|
||||||
|
tree valist, type;
|
||||||
|
{
|
||||||
|
HOST_WIDE_INT size, rsize;
|
||||||
|
tree base, tmp, pptr_type_node;
|
||||||
|
rtx addr_rtx, r;
|
||||||
|
|
||||||
|
size = int_size_in_bytes (type);
|
||||||
|
rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
|
||||||
|
pptr_type_node = build_pointer_type (ptr_type_node);
|
||||||
|
|
||||||
|
if ((TARGET_SH3E || TARGET_SH4) && ! TARGET_HITACHI)
|
||||||
|
{
|
||||||
|
tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
|
||||||
|
tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack;
|
||||||
|
int pass_as_float;
|
||||||
|
rtx lab_false, lab_over;
|
||||||
|
|
||||||
|
f_next_o = TYPE_FIELDS (va_list_type_node);
|
||||||
|
f_next_o_limit = TREE_CHAIN (f_next_o);
|
||||||
|
f_next_fp = TREE_CHAIN (f_next_o_limit);
|
||||||
|
f_next_fp_limit = TREE_CHAIN (f_next_fp);
|
||||||
|
f_next_stack = TREE_CHAIN (f_next_fp_limit);
|
||||||
|
|
||||||
|
next_o = build (COMPONENT_REF, TREE_TYPE (f_next_o), valist, f_next_o);
|
||||||
|
next_o_limit = build (COMPONENT_REF, TREE_TYPE (f_next_o_limit),
|
||||||
|
valist, f_next_o_limit);
|
||||||
|
next_fp = build (COMPONENT_REF, TREE_TYPE (f_next_fp),
|
||||||
|
valist, f_next_fp);
|
||||||
|
next_fp_limit = build (COMPONENT_REF, TREE_TYPE (f_next_fp_limit),
|
||||||
|
valist, f_next_fp_limit);
|
||||||
|
next_stack = build (COMPONENT_REF, TREE_TYPE (f_next_stack),
|
||||||
|
valist, f_next_stack);
|
||||||
|
|
||||||
|
if (TARGET_SH4)
|
||||||
|
{
|
||||||
|
pass_as_float = ((TREE_CODE (type) == REAL_TYPE && size <= 8)
|
||||||
|
|| (TREE_CODE (type) == COMPLEX_TYPE
|
||||||
|
&& TREE_CODE (TREE_TYPE (type)) == REAL_TYPE
|
||||||
|
&& size <= 16));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pass_as_float = (TREE_CODE (type) == REAL_TYPE && size == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
addr_rtx = gen_reg_rtx (Pmode);
|
||||||
|
lab_false = gen_label_rtx ();
|
||||||
|
lab_over = gen_label_rtx ();
|
||||||
|
|
||||||
|
if (pass_as_float)
|
||||||
|
{
|
||||||
|
emit_cmp_and_jump_insns (expand_expr (next_fp, NULL_RTX, Pmode,
|
||||||
|
EXPAND_NORMAL),
|
||||||
|
expand_expr (next_fp_limit, NULL_RTX,
|
||||||
|
Pmode, EXPAND_NORMAL),
|
||||||
|
GE, const1_rtx, Pmode, 1, 1, lab_false);
|
||||||
|
|
||||||
|
if (TYPE_ALIGN (type) > BITS_PER_WORD)
|
||||||
|
{
|
||||||
|
tmp = build (BIT_AND_EXPR, ptr_type_node, next_fp,
|
||||||
|
build_int_2 (UNITS_PER_WORD, 0));
|
||||||
|
tmp = build (PLUS_EXPR, ptr_type_node, next_fp, tmp);
|
||||||
|
tmp = build (MODIFY_EXPR, ptr_type_node, next_fp, tmp);
|
||||||
|
TREE_SIDE_EFFECTS (tmp) = 1;
|
||||||
|
expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = build1 (ADDR_EXPR, pptr_type_node, next_fp);
|
||||||
|
r = expand_expr (tmp, addr_rtx, Pmode, EXPAND_NORMAL);
|
||||||
|
if (r != addr_rtx)
|
||||||
|
emit_move_insn (addr_rtx, r);
|
||||||
|
|
||||||
|
emit_jump_insn (gen_jump (lab_over));
|
||||||
|
emit_barrier ();
|
||||||
|
emit_label (lab_false);
|
||||||
|
|
||||||
|
tmp = build1 (ADDR_EXPR, pptr_type_node, next_stack);
|
||||||
|
r = expand_expr (tmp, addr_rtx, Pmode, EXPAND_NORMAL);
|
||||||
|
if (r != addr_rtx)
|
||||||
|
emit_move_insn (addr_rtx, r);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmp = build (PLUS_EXPR, ptr_type_node, next_o,
|
||||||
|
build_int_2 (rsize, 0));
|
||||||
|
|
||||||
|
emit_cmp_and_jump_insns (expand_expr (tmp, NULL_RTX, Pmode,
|
||||||
|
EXPAND_NORMAL),
|
||||||
|
expand_expr (next_o_limit, NULL_RTX,
|
||||||
|
Pmode, EXPAND_NORMAL),
|
||||||
|
GT, const1_rtx, Pmode, 1, 1, lab_false);
|
||||||
|
|
||||||
|
tmp = build1 (ADDR_EXPR, pptr_type_node, next_o);
|
||||||
|
r = expand_expr (tmp, addr_rtx, Pmode, EXPAND_NORMAL);
|
||||||
|
if (r != addr_rtx)
|
||||||
|
emit_move_insn (addr_rtx, r);
|
||||||
|
|
||||||
|
emit_jump_insn (gen_jump (lab_over));
|
||||||
|
emit_barrier ();
|
||||||
|
emit_label (lab_false);
|
||||||
|
|
||||||
|
if (size > 4 && ! TARGET_SH4)
|
||||||
|
{
|
||||||
|
tmp = build (MODIFY_EXPR, ptr_type_node, next_o, next_o_limit);
|
||||||
|
TREE_SIDE_EFFECTS (tmp) = 1;
|
||||||
|
expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = build1 (ADDR_EXPR, pptr_type_node, next_stack);
|
||||||
|
r = expand_expr (tmp, addr_rtx, Pmode, EXPAND_NORMAL);
|
||||||
|
if (r != addr_rtx)
|
||||||
|
emit_move_insn (addr_rtx, r);
|
||||||
|
}
|
||||||
|
|
||||||
|
emit_label (lab_over);
|
||||||
|
|
||||||
|
tmp = make_tree (pptr_type_node, addr_rtx);
|
||||||
|
valist = build1 (INDIRECT_REF, ptr_type_node, tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ??? In va-sh.h, there had been code to make values larger than
|
||||||
|
size 8 indirect. This does not match the FUNCTION_ARG macros. */
|
||||||
|
|
||||||
|
return std_expand_builtin_va_arg (valist, type);
|
||||||
|
}
|
||||||
|
|
||||||
/* Define the offset between two registers, one to be eliminated, and
|
/* Define the offset between two registers, one to be eliminated, and
|
||||||
the other its replacement, at the start of a routine. */
|
the other its replacement, at the start of a routine. */
|
||||||
|
|
||||||
|
|
|
@ -1076,6 +1076,18 @@ extern int current_function_anonymous_args;
|
||||||
#define SETUP_INCOMING_VARARGS(ASF, MODE, TYPE, PAS, ST) \
|
#define SETUP_INCOMING_VARARGS(ASF, MODE, TYPE, PAS, ST) \
|
||||||
current_function_anonymous_args = 1;
|
current_function_anonymous_args = 1;
|
||||||
|
|
||||||
|
/* Define the `__builtin_va_list' type for the ABI. */
|
||||||
|
#define BUILD_VA_LIST_TYPE(VALIST) \
|
||||||
|
(VALIST) = sh_build_va_list ()
|
||||||
|
|
||||||
|
/* Implement `va_start' for varargs and stdarg. */
|
||||||
|
#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
|
||||||
|
sh_va_start (stdarg, valist, nextarg)
|
||||||
|
|
||||||
|
/* Implement `va_arg'. */
|
||||||
|
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
|
||||||
|
sh_va_arg (valist, type)
|
||||||
|
|
||||||
/* Call the function profiler with a given profile label.
|
/* Call the function profiler with a given profile label.
|
||||||
We use two .aligns, so as to make sure that both the .long is aligned
|
We use two .aligns, so as to make sure that both the .long is aligned
|
||||||
on a 4 byte boundary, and that the .long is a fixed distance (2 bytes)
|
on a 4 byte boundary, and that the .long is a fixed distance (2 bytes)
|
||||||
|
|
Loading…
Reference in New Issue