aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>1999-07-27 00:21:59 -0700
committerRichard Henderson <rth@gcc.gnu.org>1999-07-27 00:21:59 -0700
commita9b8384d6e8300bcbccaeaaeb60198fc24017a40 (patch)
tree0104165917c00ff14461729227dffaf37bfda17c
parentcc95be936a83c9f546c8e049272fcb7f1dc828f9 (diff)
downloadgcc-a9b8384d6e8300bcbccaeaaeb60198fc24017a40.zip
gcc-a9b8384d6e8300bcbccaeaaeb60198fc24017a40.tar.gz
gcc-a9b8384d6e8300bcbccaeaaeb60198fc24017a40.tar.bz2
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
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/config/m88k/m88k.c212
-rw-r--r--gcc/config/m88k/m88k.h19
3 files changed, 189 insertions, 53 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d1db279..3046572 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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>
* config/rs6000/rs6000.c (rs6000_expand_builtin_saveregs):
diff --git a/gcc/config/m88k/m88k.c b/gcc/config/m88k/m88k.c
index b461782..5d54fdd 100644
--- a/gcc/config/m88k/m88k.c
+++ b/gcc/config/m88k/m88k.c
@@ -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
- to determine if stdargs or varargs is used and fill in an initial
- va_list. A pointer to this constructor is returned. */
+ to determine if stdargs or varargs is used and spill as necessary.
+ We return a pointer to the spill area. */
struct rtx_def *
m88k_builtin_saveregs ()
{
- rtx block, addr, argsize, dest;
+ rtx addr, dest;
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;
int fixed;
+
variable_args_p = 1;
+ fixed = 0;
if (CONSTANT_P (current_function_arg_offset_rtx))
{
fixed = (XINT (current_function_arg_offset_rtx, 0)
+ 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. */
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 (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. */
if (fixed < 8)
@@ -2637,28 +2611,164 @@ m88k_builtin_saveregs ()
fixed * UNITS_PER_WORD));
move_block_from_reg (2 + fixed, dest, 8 - fixed,
UNITS_PER_WORD * (8 - fixed));
- }
- if (current_function_check_memory_usage)
- {
- emit_library_call (chkr_set_right_libfunc, 1, VOIDmode, 3,
- block, ptr_mode,
- 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));
+ 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));
+ }
}
- /* Return the address of the va_list constructor, but don't put it in a
- register. This fails when not optimizing and produces worse code when
- optimizing. */
- return XEXP (block, 0);
+ /* Return the address of the save area, but don't put it in a
+ register. This fails when not optimizing and produces worse code
+ when optimizing. */
+ return XEXP (addr, 0);
+}
+
+/* Define the `__builtin_va_list' type for the ABI. */
+
+tree
+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
diff --git a/gcc/config/m88k/m88k.h b/gcc/config/m88k/m88k.h
index 2eb2b1f..2fa1c94 100644
--- a/gcc/config/m88k/m88k.h
+++ b/gcc/config/m88k/m88k.h
@@ -198,13 +198,13 @@ extern char * reg_names[];
Redefined in sysv4.h, and luna.h. */
#define VERSION_INFO1 "m88k, "
#ifndef VERSION_INFO2
-#define VERSION_INFO2 "$Revision: 1.12 $"
+#define VERSION_INFO2 "$Revision: 1.13 $"
#endif
#ifndef VERSION_STRING
#define VERSION_STRING version_string
#ifdef __STDC__
-#define TM_RCS_ID "@(#)" __FILE__ " $Revision: 1.12 $ " __DATE__
+#define TM_RCS_ID "@(#)" __FILE__ " $Revision: 1.13 $ " __DATE__
#else
#define TM_RCS_ID "$What: <@(#) m88k.h,v 1.1.1.2.2.2> $"
#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. */
#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. */
#define FUNCTION_PROLOGUE(FILE, SIZE) m88k_begin_prologue(FILE, SIZE)