mips.h (struct mips_args): Clarify comments.
authorRichard Sandiford <rsandifo@redhat.com>
Sat, 25 Sep 2004 07:42:43 +0000 (07:42 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sat, 25 Sep 2004 07:42:43 +0000 (07:42 +0000)
* 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
gcc/config/mips/mips.c
gcc/config/mips/mips.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/va-arg-26.c [new file with mode: 0644]

index 2bac73bda82d209bcd5f0106d79b360d9c84fd62..bcfe5915df38434bf72315ea366a6d01f087f83a 100644 (file)
@@ -1,3 +1,11 @@
+2004-09-25  Richard Sandiford  <rsandifo@redhat.com>
+
+       * 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  <rsandifo@redhat.com>
 
        * config/mips/mips.md (loadx, storex): Define for V2SF.
index a1de622dbbf65c544c26f4e0a29e51ce3246d270..242c2f76aa013e720b96e3ef8fb5c2639562584b 100644 (file)
@@ -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);
 }
 
 
index dbae270923d7f922fc95df0f2359072dede84bab..fbfdc1f43109a19f168a5c2a4944b9b7132d5ad9 100644 (file)
@@ -2180,11 +2180,11 @@ extern enum reg_class mips_char_to_class[256];
    && !fixed_regs[N])
 \f
 /* 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.  */
index fbf0a5addb5c118e11c3eb65a9c5c3c47b4c9a09..6cf8b9229d877b4a9a3841cf698d96e80d817412 100644 (file)
@@ -1,3 +1,7 @@
+2004-09-25  Richard Sandiford  <rsandifo@redhat.com>
+
+       * gcc.c-torture/execute/va-arg-26.c: New test.
+
 2004-09-24  Zack Weinberg  <zack@codesourcery.com>
 
        * 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 (file)
index 0000000..8221e9c
--- /dev/null
@@ -0,0 +1,20 @@
+#include <stdarg.h>
+
+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);
+}