i960.c (i960_function_arg_advance): Ensure all regs marked as used if stack is also used (for va_start).

* i960/i960.c (i960_function_arg_advance): Ensure all regs marked
	as used if stack is also used (for va_start).
	(i960_setup_incoming_varargs): Rewrite to be similar to Intel's
	version, but don't allocate reg block unless necessary.

From-SVN: r9226
This commit is contained in:
Doug Evans 1995-03-23 02:41:36 +00:00
parent 28cbf42c14
commit b41ac904b7
1 changed files with 45 additions and 37 deletions

View File

@ -1,5 +1,5 @@
/* Subroutines used for code generation on intel 80960.
Copyright (C) 1992 Free Software Foundation, Inc.
Copyright (C) 1992, 1995 Free Software Foundation, Inc.
Contributed by Steven McGeady, Intel Corp.
Additional Work by Glenn Colon-Bonet, Jonathan Shapiro, Andy Wilson
Converted to GCC 2.0 by Jim Wilson and Michael Tiemann, Cygnus Support.
@ -2069,7 +2069,12 @@ i960_function_arg_advance (cum, mode, type, named)
if (size > 4 || cum->ca_nstackparms != 0
|| (size + ROUND_PARM (cum->ca_nregparms, align)) > NPARM_REGS
|| MUST_PASS_IN_STACK (mode, type))
cum->ca_nstackparms = ROUND_PARM (cum->ca_nstackparms, align) + size;
{
/* Indicate that all the registers are in use, even if all are not,
so va_start will compute the right value. */
cum->ca_nregparms = NPARM_REGS;
cum->ca_nstackparms = ROUND_PARM (cum->ca_nstackparms, align) + size;
}
else
cum->ca_nregparms = ROUND_PARM (cum->ca_nregparms, align) + size;
}
@ -2200,44 +2205,47 @@ i960_setup_incoming_varargs (cum, mode, type, pretend_size, no_rtl)
int *pretend_size;
int no_rtl;
{
if (cum->ca_nregparms < NPARM_REGS)
/* Note: for a varargs fn with only a va_alist argument, this is 0. */
int first_reg = cum->ca_nregparms;
/* Copy only unnamed register arguments to memory. If there are
any stack parms, there are no unnamed arguments in registers, and
an argument block was already allocated by the caller.
Remember that any arg bigger than 4 words is passed on the stack as
are all subsequent args.
If there are no stack arguments but there are exactly NPARM_REGS
registers, either there were no extra arguments or the caller
allocated an argument block. */
if (cum->ca_nstackparms == 0 && first_reg < NPARM_REGS && !no_rtl)
{
int first_reg_offset = cum->ca_nregparms;
rtx label = gen_label_rtx ();
rtx regblock;
if (! (no_rtl))
{
rtx label = gen_label_rtx ();
rtx regblock;
/* If arg_pointer_rtx == 0, no arguments were passed on the stack
and we need to allocate a chunk to save the registers (if any
arguments were passed on the stack the caller would allocate the
48 bytes as well). We must allocate all 48 bytes (12*4) because
va_start assumes it. */
emit_insn (gen_cmpsi (arg_pointer_rtx, const0_rtx));
emit_jump_insn (gen_bne (label));
emit_insn (gen_rtx (SET, VOIDmode, arg_pointer_rtx,
stack_pointer_rtx));
emit_insn (gen_rtx (SET, VOIDmode, stack_pointer_rtx,
memory_address (SImode,
plus_constant (stack_pointer_rtx,
48))));
emit_label (label);
/* If arg_pointer_rtx == 0, no arguments were passed on the stack
and we need to allocate a chunk to save the registers (if any
arguments were passed on the stack the caller would allocate the
48 bytes as well). We must allocate all 48 bytes (12*4) because
arg_pointer_rtx is saved at the front, the anonymous args are
saved at the end. */
emit_insn (gen_cmpsi (arg_pointer_rtx, const0_rtx));
emit_jump_insn (gen_bne (label));
emit_insn (gen_rtx (SET, VOIDmode, arg_pointer_rtx,
stack_pointer_rtx));
emit_insn (gen_rtx (SET, VOIDmode, stack_pointer_rtx,
memory_address (SImode,
plus_constant (stack_pointer_rtx,
48))));
emit_label (label);
/* Any anonymous args passed in regs? */
if (first_reg_offset + 1 < NPARM_REGS)
{
rtx regblock;
regblock = gen_rtx (MEM, BLKmode,
plus_constant (arg_pointer_rtx,
(first_reg_offset + 1) * 4));
move_block_from_reg (first_reg_offset + 1, regblock,
NPARM_REGS - first_reg_offset - 1,
((NPARM_REGS - first_reg_offset - 1)
* UNITS_PER_WORD));
}
}
/* ??? Note that we unnecessarily store one extra register for stdarg
fns. We could optimize this, but it's kept as for now. */
regblock = gen_rtx (MEM, BLKmode,
plus_constant (arg_pointer_rtx,
first_reg * 4));
move_block_from_reg (first_reg, regblock,
NPARM_REGS - first_reg,
(NPARM_REGS - first_reg) * UNITS_PER_WORD);
}
}