m88k.c (m88k_builtin_saveregs): Break out the constructor code to m88k_va_start, leaving only the register spill.
* m88k.c (m88k_builtin_saveregs): Break out the constructor code to m88k_va_start, leaving only the register spill. (m88k_build_va_list): New. (m88k_va_start): New. (m88k_va_arg): New. * m88k.h (BUILD_VA_LIST_TYPE): New. (EXPAND_BUILTIN_VA_START): New. (EXPAND_BUILTIN_VA_ARG): New. From-SVN: r28287
This commit is contained in:
parent
cc95be936a
commit
a9b8384d6e
@ -1,3 +1,14 @@
|
|||||||
|
Tue Jul 27 00:18:34 1999 Richard Henderson <rth@cygnus.com>
|
||||||
|
|
||||||
|
* m88k.c (m88k_builtin_saveregs): Break out the constructor code
|
||||||
|
to m88k_va_start, leaving only the register spill.
|
||||||
|
(m88k_build_va_list): New.
|
||||||
|
(m88k_va_start): New.
|
||||||
|
(m88k_va_arg): New.
|
||||||
|
* m88k.h (BUILD_VA_LIST_TYPE): New.
|
||||||
|
(EXPAND_BUILTIN_VA_START): New.
|
||||||
|
(EXPAND_BUILTIN_VA_ARG): New.
|
||||||
|
|
||||||
Mon Jul 26 19:07:11 1999 Geoff Keating <geoffk@cygnus.com>
|
Mon Jul 26 19:07:11 1999 Geoff Keating <geoffk@cygnus.com>
|
||||||
|
|
||||||
* config/rs6000/rs6000.c (rs6000_expand_builtin_saveregs):
|
* config/rs6000/rs6000.c (rs6000_expand_builtin_saveregs):
|
||||||
|
@ -2574,60 +2574,34 @@ m88k_function_arg (args_so_far, mode, type, named)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Do what is necessary for `va_start'. We look at the current function
|
/* Do what is necessary for `va_start'. We look at the current function
|
||||||
to determine if stdargs or varargs is used and fill in an initial
|
to determine if stdargs or varargs is used and spill as necessary.
|
||||||
va_list. A pointer to this constructor is returned. */
|
We return a pointer to the spill area. */
|
||||||
|
|
||||||
struct rtx_def *
|
struct rtx_def *
|
||||||
m88k_builtin_saveregs ()
|
m88k_builtin_saveregs ()
|
||||||
{
|
{
|
||||||
rtx block, addr, argsize, dest;
|
rtx addr, dest;
|
||||||
tree fntype = TREE_TYPE (current_function_decl);
|
tree fntype = TREE_TYPE (current_function_decl);
|
||||||
int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
|
int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
|
||||||
&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
|
&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
|
||||||
!= void_type_node)))
|
!= void_type_node)))
|
||||||
? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
|
? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
|
||||||
int fixed;
|
int fixed;
|
||||||
|
|
||||||
variable_args_p = 1;
|
variable_args_p = 1;
|
||||||
|
|
||||||
|
fixed = 0;
|
||||||
if (CONSTANT_P (current_function_arg_offset_rtx))
|
if (CONSTANT_P (current_function_arg_offset_rtx))
|
||||||
{
|
{
|
||||||
fixed = (XINT (current_function_arg_offset_rtx, 0)
|
fixed = (XINT (current_function_arg_offset_rtx, 0)
|
||||||
+ argadj) / UNITS_PER_WORD;
|
+ argadj) / UNITS_PER_WORD;
|
||||||
argsize = GEN_INT (fixed);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
fixed = 0;
|
|
||||||
argsize = plus_constant (current_function_arg_offset_rtx, argadj);
|
|
||||||
argsize = expand_shift (RSHIFT_EXPR, Pmode, argsize,
|
|
||||||
build_int_2 (2, 0), argsize, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Allocate the va_list constructor */
|
|
||||||
block = assign_stack_local (BLKmode, 3 * UNITS_PER_WORD, BITS_PER_WORD);
|
|
||||||
MEM_SET_IN_STRUCT_P (block, 1);
|
|
||||||
RTX_UNCHANGING_P (block) = 1;
|
|
||||||
RTX_UNCHANGING_P (XEXP (block, 0)) = 1;
|
|
||||||
|
|
||||||
/* Store the argsize as the __va_arg member. */
|
|
||||||
emit_move_insn (change_address (block, SImode, XEXP (block, 0)),
|
|
||||||
argsize);
|
|
||||||
|
|
||||||
/* Store the arg pointer in the __va_stk member. */
|
|
||||||
emit_move_insn (change_address (block, Pmode,
|
|
||||||
plus_constant (XEXP (block, 0),
|
|
||||||
UNITS_PER_WORD)),
|
|
||||||
copy_to_reg (virtual_incoming_args_rtx));
|
|
||||||
|
|
||||||
/* Allocate the register space, and store it as the __va_reg member. */
|
/* Allocate the register space, and store it as the __va_reg member. */
|
||||||
addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
|
addr = assign_stack_local (BLKmode, 8 * UNITS_PER_WORD, -1);
|
||||||
MEM_SET_IN_STRUCT_P (addr, 1);
|
MEM_ALIAS_SET (addr) = get_varargs_alias_set ();
|
||||||
RTX_UNCHANGING_P (addr) = 1;
|
RTX_UNCHANGING_P (addr) = 1;
|
||||||
RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
|
RTX_UNCHANGING_P (XEXP (addr, 0)) = 1;
|
||||||
emit_move_insn (change_address (block, Pmode,
|
|
||||||
plus_constant (XEXP (block, 0),
|
|
||||||
2 * UNITS_PER_WORD)),
|
|
||||||
copy_to_reg (XEXP (addr, 0)));
|
|
||||||
|
|
||||||
/* Now store the incoming registers. */
|
/* Now store the incoming registers. */
|
||||||
if (fixed < 8)
|
if (fixed < 8)
|
||||||
@ -2637,28 +2611,164 @@ m88k_builtin_saveregs ()
|
|||||||
fixed * UNITS_PER_WORD));
|
fixed * UNITS_PER_WORD));
|
||||||
move_block_from_reg (2 + fixed, dest, 8 - fixed,
|
move_block_from_reg (2 + fixed, dest, 8 - fixed,
|
||||||
UNITS_PER_WORD * (8 - fixed));
|
UNITS_PER_WORD * (8 - fixed));
|
||||||
|
|
||||||
|
if (current_function_check_memory_usage)
|
||||||
|
{
|
||||||
|
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
|
||||||
|
dest, ptr_mode,
|
||||||
|
GEN_INT (UNITS_PER_WORD * (8 - fixed)),
|
||||||
|
TYPE_MODE (sizetype),
|
||||||
|
GEN_INT (MEMORY_USE_RW),
|
||||||
|
TYPE_MODE (integer_type_node));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current_function_check_memory_usage)
|
/* Return the address of the save area, but don't put it in a
|
||||||
{
|
register. This fails when not optimizing and produces worse code
|
||||||
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
|
when optimizing. */
|
||||||
block, ptr_mode,
|
return XEXP (addr, 0);
|
||||||
GEN_INT (3 * UNITS_PER_WORD), TYPE_MODE (sizetype),
|
}
|
||||||
GEN_INT (MEMORY_USE_RW),
|
|
||||||
TYPE_MODE (integer_type_node));
|
|
||||||
if (fixed < 8)
|
|
||||||
emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
|
|
||||||
dest, ptr_mode,
|
|
||||||
GEN_INT (UNITS_PER_WORD * (8 - fixed)),
|
|
||||||
TYPE_MODE (sizetype),
|
|
||||||
GEN_INT (MEMORY_USE_RW),
|
|
||||||
TYPE_MODE (integer_type_node));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return the address of the va_list constructor, but don't put it in a
|
/* Define the `__builtin_va_list' type for the ABI. */
|
||||||
register. This fails when not optimizing and produces worse code when
|
|
||||||
optimizing. */
|
tree
|
||||||
return XEXP (block, 0);
|
m88k_build_va_list ()
|
||||||
|
{
|
||||||
|
tree field_reg, field_stk, field_arg, int_ptr_type_node, record;
|
||||||
|
|
||||||
|
int_ptr_type_node = build_pointer_type (integer_type_node);
|
||||||
|
|
||||||
|
record = make_node (RECORD_TYPE);
|
||||||
|
|
||||||
|
field_arg = build_decl (FIELD_DECL, get_identifier ("__va_arg"),
|
||||||
|
integer_type_node);
|
||||||
|
field_stk = build_decl (FIELD_DECL, get_identifier ("__va_stk"),
|
||||||
|
int_ptr_type_node);
|
||||||
|
field_reg = build_decl (FIELD_DECL, get_identifier ("__va_reg"),
|
||||||
|
int_ptr_type_node);
|
||||||
|
|
||||||
|
DECL_FIELD_CONTEXT (field_arg) = record;
|
||||||
|
DECL_FIELD_CONTEXT (field_stk) = record;
|
||||||
|
DECL_FIELD_CONTEXT (field_reg) = record;
|
||||||
|
|
||||||
|
TYPE_FIELDS (record) = field_arg;
|
||||||
|
TREE_CHAIN (field_arg) = field_stk;
|
||||||
|
TREE_CHAIN (field_stk) = field_reg;
|
||||||
|
|
||||||
|
layout_type (record);
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Implement `va_start' for varargs and stdarg. */
|
||||||
|
|
||||||
|
void
|
||||||
|
m88k_va_start (stdarg_p, valist, nextarg)
|
||||||
|
int stdarg_p;
|
||||||
|
tree valist;
|
||||||
|
rtx nextarg ATTRIBUTE_UNUSED;
|
||||||
|
{
|
||||||
|
tree field_reg, field_stk, field_arg;
|
||||||
|
tree reg, stk, arg, t;
|
||||||
|
|
||||||
|
field_arg = TYPE_FIELDS (va_list_type_node);
|
||||||
|
field_stk = TREE_CHAIN (field_arg);
|
||||||
|
field_reg = TREE_CHAIN (field_stk);
|
||||||
|
|
||||||
|
arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
|
||||||
|
stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
|
||||||
|
reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
|
||||||
|
|
||||||
|
/* Fill in the ARG member. */
|
||||||
|
{
|
||||||
|
tree fntype = TREE_TYPE (current_function_decl);
|
||||||
|
int argadj = ((!(TYPE_ARG_TYPES (fntype) != 0
|
||||||
|
&& (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
|
||||||
|
!= void_type_node)))
|
||||||
|
? -UNITS_PER_WORD : 0) + UNITS_PER_WORD - 1;
|
||||||
|
tree argsize;
|
||||||
|
|
||||||
|
if (CONSTANT_P (current_function_arg_offset_rtx))
|
||||||
|
{
|
||||||
|
int fixed = (INTVAL (current_function_arg_offset_rtx)
|
||||||
|
+ argadj) / UNITS_PER_WORD;
|
||||||
|
|
||||||
|
argsize = build_int_2 (fixed, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
argsize = make_tree (integer_type_node,
|
||||||
|
current_function_arg_offset_rtx);
|
||||||
|
argsize = fold (build (PLUS_EXPR, integer_type_node, argsize,
|
||||||
|
build_int_2 (argadj, 0)));
|
||||||
|
argsize = fold (build (RSHIFT_EXPR, integer_type_node, argsize,
|
||||||
|
build_int_2 (2, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, argsize);
|
||||||
|
TREE_SIDE_EFFECTS (t) = 1;
|
||||||
|
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store the arg pointer in the __va_stk member. */
|
||||||
|
t = make_tree (TREE_TYPE (stk), virtual_incoming_args_rtx);
|
||||||
|
t = build (MODIFY_EXPR, TREE_TYPE (stk), stk, t);
|
||||||
|
TREE_SIDE_EFFECTS (t) = 1;
|
||||||
|
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||||
|
|
||||||
|
/* Tuck the return value from __builtin_saveregs into __va_reg. */
|
||||||
|
t = make_tree (TREE_TYPE (reg), expand_builtin_saveregs ());
|
||||||
|
t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, t);
|
||||||
|
TREE_SIDE_EFFECTS (t) = 1;
|
||||||
|
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Implement `va_arg'. */
|
||||||
|
|
||||||
|
rtx
|
||||||
|
m88k_va_arg (valist, type)
|
||||||
|
tree valist, type;
|
||||||
|
{
|
||||||
|
tree field_reg, field_stk, field_arg;
|
||||||
|
tree reg, stk, arg, arg_align, base, t;
|
||||||
|
int size, wsize, align, reg_p;
|
||||||
|
rtx addr_rtx;
|
||||||
|
|
||||||
|
field_arg = TYPE_FIELDS (va_list_type_node);
|
||||||
|
field_stk = TREE_CHAIN (field_arg);
|
||||||
|
field_reg = TREE_CHAIN (field_stk);
|
||||||
|
|
||||||
|
arg = build (COMPONENT_REF, TREE_TYPE (field_arg), valist, field_arg);
|
||||||
|
stk = build (COMPONENT_REF, TREE_TYPE (field_stk), valist, field_stk);
|
||||||
|
reg = build (COMPONENT_REF, TREE_TYPE (field_reg), valist, field_reg);
|
||||||
|
|
||||||
|
size = int_size_in_bytes (type);
|
||||||
|
wsize = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
|
||||||
|
align = 1 << ((TYPE_ALIGN (type) / BITS_PER_UNIT) >> 3);
|
||||||
|
reg_p = (AGGREGATE_TYPE_P (type)
|
||||||
|
? size == UNITS_PER_WORD && TYPE_ALIGN (type) == BITS_PER_WORD
|
||||||
|
: size <= 2*UNITS_PER_WORD);
|
||||||
|
|
||||||
|
/* Align __va_arg to the (doubleword?) boundary above. */
|
||||||
|
t = build (PLUS_EXPR, TREE_TYPE (arg), arg, build_int_2 (align - 1, 0));
|
||||||
|
arg_align = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
|
||||||
|
arg_align = save_expr (arg_align);
|
||||||
|
|
||||||
|
/* Decide if we should read from stack or regs. */
|
||||||
|
t = build (LT_EXPR, integer_type_node, arg_align, build_int_2 (8, 0));
|
||||||
|
base = build (COND_EXPR, TREE_TYPE (reg), t, reg, stk);
|
||||||
|
|
||||||
|
/* Find the final address. */
|
||||||
|
t = build (PLUS_EXPR, TREE_TYPE (base), base, arg_align);
|
||||||
|
addr_rtx = expand_expr (t, NULL_RTX, Pmode, EXPAND_NORMAL);
|
||||||
|
addr_rtx = copy_to_reg (addr_rtx);
|
||||||
|
|
||||||
|
/* Increment __va_arg. */
|
||||||
|
t = build (PLUS_EXPR, TREE_TYPE (arg), arg_align, build_int_2 (wsize, 0));
|
||||||
|
t = build (MODIFY_EXPR, TREE_TYPE (arg), arg, t);
|
||||||
|
TREE_SIDE_EFFECTS (t) = 1;
|
||||||
|
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
|
||||||
|
|
||||||
|
return addr_rtx;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If cmpsi has not been generated, emit code to do the test. Return the
|
/* If cmpsi has not been generated, emit code to do the test. Return the
|
||||||
|
@ -198,13 +198,13 @@ extern char * reg_names[];
|
|||||||
Redefined in sysv4.h, and luna.h. */
|
Redefined in sysv4.h, and luna.h. */
|
||||||
#define VERSION_INFO1 "m88k, "
|
#define VERSION_INFO1 "m88k, "
|
||||||
#ifndef VERSION_INFO2
|
#ifndef VERSION_INFO2
|
||||||
#define VERSION_INFO2 "$Revision: 1.12 $"
|
#define VERSION_INFO2 "$Revision: 1.13 $"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef VERSION_STRING
|
#ifndef VERSION_STRING
|
||||||
#define VERSION_STRING version_string
|
#define VERSION_STRING version_string
|
||||||
#ifdef __STDC__
|
#ifdef __STDC__
|
||||||
#define TM_RCS_ID "@(#)" __FILE__ " $Revision: 1.12 $ " __DATE__
|
#define TM_RCS_ID "@(#)" __FILE__ " $Revision: 1.13 $ " __DATE__
|
||||||
#else
|
#else
|
||||||
#define TM_RCS_ID "$What: <@(#) m88k.h,v 1.1.1.2.2.2> $"
|
#define TM_RCS_ID "$What: <@(#) m88k.h,v 1.1.1.2.2.2> $"
|
||||||
#endif /* __STDC__ */
|
#endif /* __STDC__ */
|
||||||
@ -1095,6 +1095,21 @@ enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS,
|
|||||||
ARGLIST is the argument list; see expr.c. */
|
ARGLIST is the argument list; see expr.c. */
|
||||||
#define EXPAND_BUILTIN_SAVEREGS() m88k_builtin_saveregs ()
|
#define EXPAND_BUILTIN_SAVEREGS() m88k_builtin_saveregs ()
|
||||||
|
|
||||||
|
/* Define the `__builtin_va_list' type for the ABI. */
|
||||||
|
#define BUILD_VA_LIST_TYPE(VALIST) \
|
||||||
|
(VALIST) = m88k_build_va_list ()
|
||||||
|
extern union tree_node *m88k_build_va_list ();
|
||||||
|
|
||||||
|
/* Implement `va_start' for varargs and stdarg. */
|
||||||
|
#define EXPAND_BUILTIN_VA_START(stdarg, valist, nextarg) \
|
||||||
|
m88k_va_start (stdarg, valist, nextarg)
|
||||||
|
extern void m88k_va_start ();
|
||||||
|
|
||||||
|
/* Implement `va_arg'. */
|
||||||
|
#define EXPAND_BUILTIN_VA_ARG(valist, type) \
|
||||||
|
m88k_va_arg (valist, type)
|
||||||
|
extern struct rtx_def *m88k_va_arg ();
|
||||||
|
|
||||||
/* Generate the assembly code for function entry. */
|
/* Generate the assembly code for function entry. */
|
||||||
#define FUNCTION_PROLOGUE(FILE, SIZE) m88k_begin_prologue(FILE, SIZE)
|
#define FUNCTION_PROLOGUE(FILE, SIZE) m88k_begin_prologue(FILE, SIZE)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user