2008-06-03 Michael Snyder <msnyder@redhat.com>
authorJoseph Myers <joseph@codesourcery.com>
Tue, 3 Jun 2008 10:53:34 +0000 (10:53 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Tue, 3 Jun 2008 10:53:34 +0000 (10:53 +0000)
            Joseph Myers  <joseph@codesourcery.com>

* mips-tdep.c (mips_eabi_return_value): Replace stub that always
returned RETURN_VALUE_STRUCT_CONVENTION with a real function.

gdb/ChangeLog
gdb/mips-tdep.c

index 08a01c742e54014291547e8eae603a0b54c9a936..5f4fbba5f9b53f4d99d89b3f622b4034fe1c864d 100644 (file)
@@ -1,3 +1,9 @@
+2008-06-03  Michael Snyder  <msnyder@redhat.com>
+            Joseph Myers  <joseph@codesourcery.com>
+
+       * mips-tdep.c (mips_eabi_return_value): Replace stub that always
+       returned RETURN_VALUE_STRUCT_CONVENTION with a real function.
+
 2008-06-02  Roman Zippel <zippel@linux-m68k.org>
 
        * m68klinux-tdep.c (m68k_linux_pc_in_sigtramp): Fix incorrect test.
index 6277407695ddd46cbf9cfc91806524fcf3fd8ffd..976bcf7f0e651eaef821bc1eed94bdb9be06f48f 100644 (file)
@@ -2956,10 +2956,59 @@ mips_eabi_return_value (struct gdbarch *gdbarch, struct type *func_type,
                        struct type *type, struct regcache *regcache,
                        gdb_byte *readbuf, const gdb_byte *writebuf)
 {
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int fp_return_type = 0;
+  int offset, regnum, xfer;
+
   if (TYPE_LENGTH (type) > 2 * mips_abi_regsize (gdbarch))
     return RETURN_VALUE_STRUCT_CONVENTION;
-  if (readbuf)
-    memset (readbuf, 0, TYPE_LENGTH (type));
+
+  /* Floating point type?  */
+  if (tdep->mips_fpu_type != MIPS_FPU_NONE)
+    {
+      if (TYPE_CODE (type) == TYPE_CODE_FLT)
+       fp_return_type = 1;
+      /* Structs with a single field of float type 
+        are returned in a floating point register.  */
+      if ((TYPE_CODE (type) == TYPE_CODE_STRUCT
+          || TYPE_CODE (type) == TYPE_CODE_UNION)
+         && TYPE_NFIELDS (type) == 1)
+       {
+         struct type *fieldtype = TYPE_FIELD_TYPE (type, 0);
+
+         if (TYPE_CODE (check_typedef (fieldtype)) == TYPE_CODE_FLT)
+           fp_return_type = 1;
+       }
+    }
+
+  if (fp_return_type)      
+    {
+      /* A floating-point value belongs in the least significant part
+        of FP0/FP1.  */
+      if (mips_debug)
+       fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n");
+      regnum = mips_regnum (gdbarch)->fp0;
+    }
+  else 
+    {
+      /* An integer value goes in V0/V1.  */
+      if (mips_debug)
+       fprintf_unfiltered (gdb_stderr, "Return scalar in $v0\n");
+      regnum = MIPS_V0_REGNUM;
+    }
+  for (offset = 0;
+       offset < TYPE_LENGTH (type);
+       offset += mips_abi_regsize (gdbarch), regnum++)
+    {
+      xfer = mips_abi_regsize (gdbarch);
+      if (offset + xfer > TYPE_LENGTH (type))
+       xfer = TYPE_LENGTH (type) - offset;
+      mips_xfer_register (gdbarch, regcache,
+                         gdbarch_num_regs (gdbarch) + regnum, xfer,
+                         gdbarch_byte_order (gdbarch), readbuf, writebuf,
+                         offset);
+    }
+
   return RETURN_VALUE_REGISTER_CONVENTION;
 }