abi64.h (SETUP_INCOMING_VARARGS): Undefine.

* config/mips/abi64.h (SETUP_INCOMING_VARARGS): Undefine.
	* config/mips/mips-protos.h (mips_setup_incoming_varargs): Declare.
	(function_arg): Constify CUMULATIVE_ARGS.
	(function_arg_partial_nregs, function_arg_pass_by_reference): Likewise.
	* config/mips/mips.h (UNITS_PER_FPVALUE): Zero when TARGET_SOFT_FLOAT.
	(UNITS_PER_DOUBLE): New macro.
	(SETUP_INCOMING_VARARGS): Define.  Use mips_setup_incoming_varargs.
	(CUMULATIVE_ARGS): Reformat.  Remove num_adjusts workaround and
	last_arg_fp field.  Replace arg_words and fp_arg_words with gp_regs,
	fp_regs and stack_words.
	(EABI_FLOAT_VARARGS_P): New macro.
	* config/mips/mips.c (struct mips_arg_info): New.
	(mips_arg_info): New function.
	(function_arg_advance): Use it.  Add adjustment instructions here
	rather than in function_arg.
	(function_arg): Constify CUMULATIVE_ARGS.  Use mips_arg_info.  Check
	for VOIDmode at the beginning of the function.
	(function_partial_nregs): Constify CUMULATIVE_ARGS.  Use mips_arg_info.
	(function_arg_pass_by_reference): Likewise.
	(mips_setup_incoming_varags): New, largely based on old abi64.h code.
	(mips_build_va_list): Test EABI_FLOAT_VARARGS_P.
	(mips_va_start): Likewise.  Use the new stack_words field of
	CUMULATIVE_ARGS to set up overflow area.  Reformat.
	(mips_va_arg): Test EABI_FLOAT_VARARGS_P.  Unify EABI handling of
	doubles and other types, aligning the overflow pointer for non-doubles
	too.  Remove some code duplication.  Replace hard-coded constants.

From-SVN: r51167
This commit is contained in:
Richard Sandiford 2002-03-22 09:55:03 +00:00 committed by Richard Sandiford
parent e6f884cdac
commit 4d72536eec
5 changed files with 661 additions and 725 deletions

View file

@ -1,3 +1,32 @@
2002-03-22 Richard Sandiford <rsandifo@redhat.com>
* config/mips/abi64.h (SETUP_INCOMING_VARARGS): Undefine.
* config/mips/mips-protos.h (mips_setup_incoming_varargs): Declare.
(function_arg): Constify CUMULATIVE_ARGS.
(function_arg_partial_nregs, function_arg_pass_by_reference): Likewise.
* config/mips/mips.h (UNITS_PER_FPVALUE): Zero when TARGET_SOFT_FLOAT.
(UNITS_PER_DOUBLE): New macro.
(SETUP_INCOMING_VARARGS): Define. Use mips_setup_incoming_varargs.
(CUMULATIVE_ARGS): Reformat. Remove num_adjusts workaround and
last_arg_fp field. Replace arg_words and fp_arg_words with gp_regs,
fp_regs and stack_words.
(EABI_FLOAT_VARARGS_P): New macro.
* config/mips/mips.c (struct mips_arg_info): New.
(mips_arg_info): New function.
(function_arg_advance): Use it. Add adjustment instructions here
rather than in function_arg.
(function_arg): Constify CUMULATIVE_ARGS. Use mips_arg_info. Check
for VOIDmode at the beginning of the function.
(function_partial_nregs): Constify CUMULATIVE_ARGS. Use mips_arg_info.
(function_arg_pass_by_reference): Likewise.
(mips_setup_incoming_varags): New, largely based on old abi64.h code.
(mips_build_va_list): Test EABI_FLOAT_VARARGS_P.
(mips_va_start): Likewise. Use the new stack_words field of
CUMULATIVE_ARGS to set up overflow area. Reformat.
(mips_va_arg): Test EABI_FLOAT_VARARGS_P. Unify EABI handling of
doubles and other types, aligning the overflow pointer for non-doubles
too. Remove some code duplication. Replace hard-coded constants.
2002-03-22 Richard Sandiford <rsandifo@redhat.com>
* config/mips/mips.h (FUNCTION_ARG_REGNO_P): Simplify.

View file

@ -102,96 +102,6 @@ Boston, MA 02111-1307, USA. */
#undef FUNCTION_VALUE
#define FUNCTION_VALUE(VALTYPE, FUNC) mips_function_value (VALTYPE, FUNC)
/* For varargs, we must save the current argument, because it is the fake
argument va_alist, and will need to be converted to the real argument.
For stdarg, we do not need to save the current argument, because it
is a real argument. */
#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
{ unsigned int mips_off \
= (! current_function_varargs) && (! (CUM).last_arg_fp); \
unsigned int mips_fp_off \
= (! current_function_varargs) && ((CUM).last_arg_fp); \
if (((mips_abi != ABI_32 && mips_abi != ABI_O64) \
&& (CUM).arg_words < MAX_ARGS_IN_REGISTERS - mips_off) \
|| (mips_abi == ABI_EABI \
&& ! TARGET_SOFT_FLOAT \
&& (CUM).fp_arg_words < MAX_ARGS_IN_REGISTERS - mips_fp_off)) \
{ \
int mips_save_gp_regs \
= MAX_ARGS_IN_REGISTERS - (CUM).arg_words - mips_off; \
int mips_save_fp_regs \
= (mips_abi != ABI_EABI ? 0 \
: MAX_ARGS_IN_REGISTERS - (CUM).fp_arg_words - mips_fp_off); \
\
if (mips_save_gp_regs < 0) \
mips_save_gp_regs = 0; \
if (mips_save_fp_regs < 0) \
mips_save_fp_regs = 0; \
PRETEND_SIZE = ((mips_save_gp_regs * UNITS_PER_WORD) \
+ (mips_save_fp_regs * UNITS_PER_FPREG)); \
\
if (! (NO_RTL)) \
{ \
if ((CUM).arg_words < MAX_ARGS_IN_REGISTERS - mips_off) \
{ \
rtx ptr, mem; \
if (mips_abi != ABI_EABI) \
ptr = virtual_incoming_args_rtx; \
else \
ptr = plus_constant (virtual_incoming_args_rtx, \
- (mips_save_gp_regs \
* UNITS_PER_WORD)); \
mem = gen_rtx_MEM (BLKmode, ptr); \
/* va_arg is an array access in this case, which causes \
it to get MEM_IN_STRUCT_P set. We must set it here \
so that the insn scheduler won't assume that these \
stores can't possibly overlap with the va_arg loads. */ \
if (mips_abi != ABI_EABI && BYTES_BIG_ENDIAN) \
MEM_SET_IN_STRUCT_P (mem, 1); \
move_block_from_reg \
((CUM).arg_words + GP_ARG_FIRST + mips_off, \
mem, \
mips_save_gp_regs, \
mips_save_gp_regs * UNITS_PER_WORD); \
} \
if (mips_abi == ABI_EABI \
&& ! TARGET_SOFT_FLOAT \
&& (CUM).fp_arg_words < MAX_ARGS_IN_REGISTERS - mips_fp_off) \
{ \
enum machine_mode mode = TARGET_SINGLE_FLOAT ? SFmode : DFmode; \
int size = GET_MODE_SIZE (mode); \
int off; \
int i; \
/* We can't use move_block_from_reg, because it will use \
the wrong mode. */ \
off = - (mips_save_gp_regs * UNITS_PER_WORD); \
if (! TARGET_SINGLE_FLOAT) \
off &= ~ 7; \
if (! TARGET_FLOAT64 || TARGET_SINGLE_FLOAT) \
off -= (mips_save_fp_regs / 2) * size; \
else \
off -= mips_save_fp_regs * size; \
for (i = 0; i < mips_save_fp_regs; i++) \
{ \
rtx tem = \
gen_rtx_MEM (mode, \
plus_constant (virtual_incoming_args_rtx, \
off)); \
emit_move_insn (tem, \
gen_rtx_REG (mode, \
((CUM).fp_arg_words \
+ FP_ARG_FIRST \
+ i \
+ mips_fp_off))); \
off += size; \
if (! TARGET_FLOAT64 || TARGET_SINGLE_FLOAT) \
++i; \
} \
} \
} \
} \
}
#define STRICT_ARGUMENT_NAMING (mips_abi != ABI_32 && mips_abi != ABI_O64)
/* A C expression that indicates when an argument must be passed by

View file

@ -56,16 +56,21 @@ extern unsigned int mips_hard_regno_nregs PARAMS ((int,
enum machine_mode));
extern int mips_return_in_memory PARAMS ((tree));
extern struct rtx_def *function_arg PARAMS ((CUMULATIVE_ARGS *,
extern struct rtx_def *function_arg PARAMS ((const CUMULATIVE_ARGS *,
enum machine_mode, tree, int));
extern void function_arg_advance PARAMS ((CUMULATIVE_ARGS *,
enum machine_mode,
tree, int));
extern int function_arg_partial_nregs PARAMS ((CUMULATIVE_ARGS *,
enum machine_mode,
tree, int));
extern int function_arg_partial_nregs
PARAMS ((const CUMULATIVE_ARGS *,
enum machine_mode,
tree, int));
extern int mips_setup_incoming_varargs
PARAMS ((const CUMULATIVE_ARGS *,
enum machine_mode,
tree, int));
extern int function_arg_pass_by_reference
PARAMS ((CUMULATIVE_ARGS *,
PARAMS ((const CUMULATIVE_ARGS *,
enum machine_mode, tree, int));
extern int mips16_constant_after_function_p PARAMS ((tree));
extern int mips_output_external PARAMS ((FILE *, tree,

File diff suppressed because it is too large Load diff

View file

@ -1595,7 +1595,10 @@ do { \
#define FP_INC (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT ? 1 : 2)
/* The largest size of value that can be held in floating-point registers. */
#define UNITS_PER_FPVALUE (FP_INC * UNITS_PER_FPREG)
#define UNITS_PER_FPVALUE (TARGET_SOFT_FLOAT ? 0 : FP_INC * UNITS_PER_FPREG)
/* The number of bytes in a double. */
#define UNITS_PER_DOUBLE (TYPE_PRECISION (double_type_node) / BITS_PER_UNIT)
/* A C expression for the size in bits of the type `int' on the
target machine. If you don't define this, the default is one
@ -2737,6 +2740,10 @@ extern struct mips_frame_info current_frame_info;
#define RETURN_IN_MEMORY(TYPE) \
mips_return_in_memory (TYPE)
#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
(PRETEND_SIZE) = mips_setup_incoming_varargs (&(CUM), (MODE), \
(TYPE), (NO_RTL))
#define TARGET_FLOAT_FORMAT IEEE_FLOAT_FORMAT
@ -2748,32 +2755,75 @@ extern struct mips_frame_info current_frame_info;
and about the args processed so far, enough to enable macros
such as FUNCTION_ARG to determine where the next arg should go.
On the mips16, we need to keep track of which floating point
arguments were passed in general registers, but would have been
passed in the FP regs if this were a 32 bit function, so that we
can move them to the FP regs if we wind up calling a 32 bit
function. We record this information in fp_code, encoded in base
four. A zero digit means no floating point argument, a one digit
means an SFmode argument, and a two digit means a DFmode argument,
and a three digit is not used. The low order digit is the first
argument. Thus 6 == 1 * 4 + 2 means a DFmode argument followed by
an SFmode argument. ??? A more sophisticated approach will be
needed if MIPS_ABI != ABI_32. */
This structure has to cope with two different argument allocation
schemes. Most MIPS ABIs view the arguments as a struct, of which the
first N words go in registers and the rest go on the stack. If I < N,
the Ith word might go in Ith integer argument register or the
Ith floating-point one. In some cases, it has to go in both (see
function_arg). For these ABIs, we only need to remember the number
of words passed so far.
The EABI instead allocates the integer and floating-point arguments
separately. The first N words of FP arguments go in FP registers,
the rest go on the stack. Likewise, the first N words of the other
arguments go in integer registers, and the rest go on the stack. We
need to maintain three counts: the number of integer registers used,
the number of floating-point registers used, and the number of words
passed on the stack.
We could keep separate information for the two ABIs (a word count for
the standard ABIs, and three separate counts for the EABI). But it
seems simpler to view the standard ABIs as forms of EABI that do not
allocate floating-point registers.
So for the standard ABIs, the first N words are allocated to integer
registers, and function_arg decides on an argument-by-argument basis
whether that argument should really go in an integer register, or in
a floating-point one. */
typedef struct mips_args {
int gp_reg_found; /* whether a gp register was found yet */
unsigned int arg_number; /* argument number */
unsigned int arg_words; /* # total words the arguments take */
unsigned int fp_arg_words; /* # words for FP args (MIPS_EABI only) */
int last_arg_fp; /* nonzero if last arg was FP (EABI only) */
int fp_code; /* Mode of FP arguments (mips16) */
unsigned int num_adjusts; /* number of adjustments made */
/* Adjustments made to args pass in regs. */
/* ??? The size is doubled to work around a
bug in the code that sets the adjustments
in function_arg. */
int prototype; /* True if the function has a prototype. */
struct rtx_def *adjust[MAX_ARGS_IN_REGISTERS*2];
/* Always true for varargs functions. Otherwise true if at least
one argument has been passed in an integer register. */
int gp_reg_found;
/* The number of arguments seen so far. */
unsigned int arg_number;
/* For EABI, the number of integer registers used so far. For other
ABIs, the number of words passed in registers (whether integer
or floating-point). */
unsigned int gp_regs;
/* For EABI, the number of floating-point registers used so far. */
unsigned int fp_regs;
/* The number of words passed on the stack. */
unsigned int stack_words;
/* On the mips16, we need to keep track of which floating point
arguments were passed in general registers, but would have been
passed in the FP regs if this were a 32 bit function, so that we
can move them to the FP regs if we wind up calling a 32 bit
function. We record this information in fp_code, encoded in base
four. A zero digit means no floating point argument, a one digit
means an SFmode argument, and a two digit means a DFmode argument,
and a three digit is not used. The low order digit is the first
argument. Thus 6 == 1 * 4 + 2 means a DFmode argument followed by
an SFmode argument. ??? A more sophisticated approach will be
needed if MIPS_ABI != ABI_32. */
int fp_code;
/* True if the function has a prototype. */
int prototype;
/* When a structure does not take up a full register, the argument
should sometimes be shifted left so that it occupies the high part
of the register. These two fields describe an array of ashl
patterns for doing this. See function_arg_advance, which creates
the shift patterns, and function_arg, which returns them when given
a VOIDmode argument. */
unsigned int num_adjusts;
struct rtx_def *adjust[MAX_ARGS_IN_REGISTERS];
} CUMULATIVE_ARGS;
/* Initialize a variable CUM of type CUMULATIVE_ARGS
@ -2828,6 +2878,12 @@ typedef struct mips_args {
? PARM_BOUNDARY \
: GET_MODE_ALIGNMENT(MODE)))
/* True if using EABI and varargs can be passed in floating-point
registers. Under these conditions, we need a more complex form
of va_list, which tracks GPR, FPR and stack arguments separately. */
#define EABI_FLOAT_VARARGS_P \
(mips_abi == ABI_EABI && UNITS_PER_FPVALUE >= UNITS_PER_DOUBLE)
/* Tell prologue and epilogue if register REGNO should be saved / restored. */