From b11a9d5f3f9026dea9508e77eeeeffd28b5ae9dc Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sat, 25 Sep 2004 07:42:43 +0000 Subject: [PATCH] mips.h (struct mips_args): Clarify comments. * config/mips/mips.h (struct mips_args): Clarify comments. * config/mips/mips.c (struct mips_arg_info): Likewise. (mips_arg_info): Don't allow fpr_p to affect the register or stack alignment. Remove o64 silliness. (function_arg): Deal with the o32 float,float case specially. From-SVN: r88090 --- gcc/ChangeLog | 8 +++ gcc/config/mips/mips.c | 52 ++++++++----------- gcc/config/mips/mips.h | 16 +++--- gcc/testsuite/ChangeLog | 4 ++ .../gcc.c-torture/execute/va-arg-26.c | 20 +++++++ 5 files changed, 62 insertions(+), 38 deletions(-) create mode 100644 gcc/testsuite/gcc.c-torture/execute/va-arg-26.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2bac73bda82..bcfe5915df3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2004-09-25 Richard Sandiford + + * config/mips/mips.h (struct mips_args): Clarify comments. + * config/mips/mips.c (struct mips_arg_info): Likewise. + (mips_arg_info): Don't allow fpr_p to affect the register or + stack alignment. Remove o64 silliness. + (function_arg): Deal with the o32 float,float case specially. + 2004-09-25 Richard Sandiford * config/mips/mips.md (loadx, storex): Define for V2SF. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index a1de622dbbf..242c2f76aa0 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -419,8 +419,12 @@ struct mips_arg_info /* The number of words passed in registers, rounded up. */ unsigned int reg_words; - /* The offset of the first register from GP_ARG_FIRST or FP_ARG_FIRST, - or MAX_ARGS_IN_REGISTERS if the argument is passed entirely + /* For EABI, the offset of the first register from GP_ARG_FIRST or + FP_ARG_FIRST. For other ABIs, the offset of the first register from + the start of the ABI's argument structure (see the CUMULATIVE_ARGS + comment for details). + + The value is MAX_ARGS_IN_REGISTERS if the argument is passed entirely on the stack. */ unsigned int reg_offset; @@ -3046,7 +3050,7 @@ static void mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type, int named, struct mips_arg_info *info) { - bool even_reg_p; + bool doubleword_aligned_p; unsigned int num_bytes, num_words, max_regs; /* Work out the size of the argument. */ @@ -3123,27 +3127,10 @@ mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode, gcc_unreachable (); } - /* Now decide whether the argument must go in an even-numbered register. - Usually this is determined by type alignment, but there are two - exceptions: - - - Under the O64 ABI, the second float argument goes in $f14 if it - is single precision (doubles go in $f13 as expected). - - - Floats passed in FPRs must be in an even-numbered register if - we're using paired FPRs. */ - if (type) - even_reg_p = TYPE_ALIGN (type) > BITS_PER_WORD; - else - even_reg_p = GET_MODE_UNIT_SIZE (mode) > UNITS_PER_WORD; - - if (info->fpr_p) - { - if (mips_abi == ABI_O64 && mode == SFmode) - even_reg_p = true; - if (FP_INC > 1) - even_reg_p = true; - } + /* See whether the argument has doubleword alignment. */ + doubleword_aligned_p = (type + ? TYPE_ALIGN (type) > BITS_PER_WORD + : GET_MODE_UNIT_SIZE (mode) > UNITS_PER_WORD); /* Set REG_OFFSET to the register count we're interested in. The EABI allocates the floating-point registers separately, @@ -3152,12 +3139,13 @@ mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode, ? cum->num_fprs : cum->num_gprs); - if (even_reg_p) + /* Advance to an even register if the argument is doubleword-aligned. */ + if (doubleword_aligned_p) info->reg_offset += info->reg_offset & 1; - /* The alignment applied to registers is also applied to stack arguments. */ + /* Work out the offset of a stack argument. */ info->stack_offset = cum->stack_words; - if (even_reg_p) + if (doubleword_aligned_p) info->stack_offset += info->stack_offset & 1; max_regs = MAX_ARGS_IN_REGISTERS - info->reg_offset; @@ -3311,10 +3299,14 @@ function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, return gen_rtx_PARALLEL (mode, gen_rtvec (2, real, imag)); } - if (info.fpr_p) - return gen_rtx_REG (mode, FP_ARG_FIRST + info.reg_offset); - else + if (!info.fpr_p) return gen_rtx_REG (mode, GP_ARG_FIRST + info.reg_offset); + else if (info.reg_offset == 1) + /* This code handles the special o32 case in which the second word + of the argument structure is passed in floating-point registers. */ + return gen_rtx_REG (mode, FP_ARG_FIRST + FP_INC); + else + return gen_rtx_REG (mode, FP_ARG_FIRST + info.reg_offset); } diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index dbae270923d..fbfdc1f4310 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -2180,11 +2180,11 @@ extern enum reg_class mips_char_to_class[256]; && !fixed_regs[N]) /* 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. For these ABIs, we only need to remember - the number of words passed so far. + schemes. Most MIPS ABIs view the arguments as a structure, 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 in a + floating-point register. For these ABIs, we only need to remember + the offset of the current argument into the structure. The EABI instead allocates the integer and floating-point arguments separately. The first N words of FP arguments go in FP registers, @@ -2212,9 +2212,9 @@ typedef struct mips_args { /* 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). */ + /* The number of integer registers used so far. For all ABIs except + EABI, this is the number of words that have been added to the + argument structure, limited to MAX_ARGS_IN_REGISTERS. */ unsigned int num_gprs; /* For EABI, the number of floating-point registers used so far. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index fbf0a5addb5..6cf8b9229d8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2004-09-25 Richard Sandiford + + * gcc.c-torture/execute/va-arg-26.c: New test. + 2004-09-24 Zack Weinberg * objc.dg/proto-lossage-4.m: Use long instead of int to avoid diff --git a/gcc/testsuite/gcc.c-torture/execute/va-arg-26.c b/gcc/testsuite/gcc.c-torture/execute/va-arg-26.c new file mode 100644 index 00000000000..8221e9c42a5 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/execute/va-arg-26.c @@ -0,0 +1,20 @@ +#include + +double f (float f1, float f2, float f3, float f4, + float f5, float f6, ...) +{ + va_list ap; + double d; + + va_start (ap, f6); + d = va_arg (ap, double); + va_end (ap); + return d; +} + +int main () +{ + if (f (1, 2, 3, 4, 5, 6, 7.0) != 7.0) + abort (); + exit (0); +} -- 2.30.2