Mon Jun 30 17:54:51 1997 Michael Snyder (msnyder@cleaver.cygnus.com)
authorMichael Snyder <msnyder@vmware.com>
Tue, 1 Jul 1997 00:57:19 +0000 (00:57 +0000)
committerMichael Snyder <msnyder@vmware.com>
Tue, 1 Jul 1997 00:57:19 +0000 (00:57 +0000)
        * mips-tdep.c (mips_push_arguments): special-case handling for
        odd-sized struct parameters passed in registers / on stack.

gdb/ChangeLog
gdb/mips-tdep.c

index b63a6cd6ead0e3cd34669850ae097f6b42503b0b..4cf2199cfcbef2855ed40b6c648cbcad0276a57d 100644 (file)
@@ -1,3 +1,8 @@
+Mon Jun 30 17:54:51 1997  Michael Snyder  (msnyder@cleaver.cygnus.com)
+
+       * mips-tdep.c (mips_push_arguments): special-case handling for
+       odd-sized struct parameters passed in registers / on stack.
+
 Mon Jun 30 15:30:38 1997  Michael Snyder  (msnyder@cleaver.cygnus.com)
 
        * mips-tdep.c (mips_push_arguments): tweak alignment of small
index e08be0f1123f46821b9b643a6bff219b93325e2d..f68ecee496ac7e9ba1bc5d18d4c93a4badfac405 100644 (file)
@@ -1226,7 +1226,7 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
   int float_argreg;
   int argnum;
   int len = 0;
-  int stack_offset;
+  int stack_offset = 0;
 
   /* Macros to round N up or down to the next A boundary; A must be
      a power of two. */
@@ -1254,11 +1254,6 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
   if (struct_return)
       write_register (argreg++, struct_addr);
 
-  /* The offset onto the stack at which we will start copying parameters
-     (after the registers are used up) begins at 16 in the old ABI.
-     This leaves room for the "home" area for register parameters.  */
-  stack_offset = MIPS_EABI ? 0 : MIPS_REGSIZE * 4;
-
   /* Now load as many as possible of the first arguments into
      registers, and push the rest onto the stack.  Loop thru args
      from first to last.  */
@@ -1273,7 +1268,8 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
 
       /* The EABI passes structures that do not fit in a register by
         reference. In all other cases, pass the structure by value.  */
-      if (typecode == TYPE_CODE_STRUCT && MIPS_EABI && len > MIPS_REGSIZE)
+      if (MIPS_EABI && len > MIPS_REGSIZE &&
+         (typecode == TYPE_CODE_STRUCT || typecode == TYPE_CODE_UNION))
        {
          store_address (valbuf, MIPS_REGSIZE, VALUE_ADDRESS (arg));
          typecode = TYPE_CODE_PTR;
@@ -1341,10 +1337,40 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
          /* Copy the argument to general registers or the stack in
             register-sized pieces.  Large arguments are split between
             registers and stack.  */
+         /* Note: structs whose size is not a multiple of MIPS_REGSIZE
+            are treated specially: Irix cc passes them in registers
+            where gcc sometimes puts them on the stack.  For maximum
+            compatibility, we will put them in both places.  */
+
+         int odd_sized_struct = ((len > MIPS_REGSIZE) && 
+                                 (len % MIPS_REGSIZE != 0));
          while (len > 0)
            {
              int partial_len = len < MIPS_REGSIZE ? len : MIPS_REGSIZE;
 
+             if (argreg > MIPS_LAST_ARG_REGNUM || odd_sized_struct)
+               {
+                 /* Write this portion of the argument to the stack.  */
+                 int longword_offset;
+
+                 longword_offset = 0;
+                 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
+                   if (MIPS_REGSIZE == 8 &&
+                       (typecode == TYPE_CODE_INT ||
+                        typecode == TYPE_CODE_PTR ||
+                        typecode == TYPE_CODE_FLT) && len <= 4)
+                     longword_offset = 4;
+                   else if ((typecode == TYPE_CODE_STRUCT ||
+                             typecode == TYPE_CODE_UNION) &&
+                            TYPE_LENGTH (arg_type) < MIPS_REGSIZE)
+                     longword_offset = MIPS_REGSIZE - len;
+
+                 write_memory (sp + stack_offset + longword_offset, 
+                               val, partial_len);
+               }
+
+             /* Note!!! This is NOT an else clause.
+                Odd sized structs may go thru BOTH paths.  */
              if (argreg <= MIPS_LAST_ARG_REGNUM)
                {
                  CORE_ADDR regval = extract_address (val, partial_len);
@@ -1375,30 +1401,21 @@ mips_push_arguments(nargs, args, sp, struct_return, struct_addr)
                  if (!MIPS_EABI)
                    float_argreg = MIPS_LAST_FP_ARG_REGNUM + 1;
                }
-             else
-               {
-                 /* Write this portion of the argument to the stack.  */
-                 int longword_offset;
-
-                 partial_len = len;
-                 longword_offset = 0;
-                 if (TARGET_BYTE_ORDER == BIG_ENDIAN)
-                   if (MIPS_REGSIZE == 8 &&
-                       (typecode == TYPE_CODE_INT ||
-                        typecode == TYPE_CODE_PTR ||
-                        typecode == TYPE_CODE_FLT) && len <= 4)
-                     longword_offset = 4;
-                   else if ((typecode == TYPE_CODE_STRUCT ||
-                             typecode == TYPE_CODE_UNION) &&
-                            len < MIPS_REGSIZE)
-                     longword_offset = MIPS_REGSIZE - len;
-                 write_memory (sp + stack_offset + longword_offset, 
-                               val, partial_len);
-                 stack_offset += ROUND_UP (partial_len, MIPS_REGSIZE);
-               }
     
              len -= partial_len;
              val += partial_len;
+
+             /* The offset onto the stack at which we will start
+                copying parameters (after the registers are used up) 
+                begins at (4 * MIPS_REGSIZE) in the old ABI.  This 
+                leaves room for the "home" area for register parameters.
+
+                In the new EABI, the 8 register parameters do not 
+                have "home" stack space reserved for them, so the
+                stack offset does not get incremented until after
+                we have used up the 8 parameter registers.  */
+             if (!(MIPS_EABI && argnum < 8))
+               stack_offset += ROUND_UP (partial_len, MIPS_REGSIZE);
            }
        }
     }
@@ -1568,7 +1585,7 @@ mips_print_register (regnum, all)
       return;
     }
 
-  /* If an even floating pointer register, also print as double. */
+  /* If an even floating point register, also print as double. */
   if (regnum >= FP0_REGNUM && regnum < FP0_REGNUM+MIPS_NUMREGS
       && !((regnum-FP0_REGNUM) & 1))
     {