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:
Richard Henderson 1999-07-27 00:21:59 -07:00 committed by Richard Henderson
parent cc95be936a
commit a9b8384d6e
3 changed files with 189 additions and 53 deletions

View File

@ -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):

View File

@ -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

View File

@ -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)