diff options
author | Joseph Myers <joseph@codesourcery.com> | 2008-06-03 10:53:34 +0000 |
---|---|---|
committer | Joseph Myers <joseph@codesourcery.com> | 2008-06-03 10:53:34 +0000 |
commit | 609ba7801aaaa100fd380f64442004426cd2976b (patch) | |
tree | c3a5f4d040d9a09afee5247ab5b4fcab7cf65351 /gdb/mips-tdep.c | |
parent | 7317d334006e42d356031e370e12c234f7401272 (diff) | |
download | gdb-609ba7801aaaa100fd380f64442004426cd2976b.zip gdb-609ba7801aaaa100fd380f64442004426cd2976b.tar.gz gdb-609ba7801aaaa100fd380f64442004426cd2976b.tar.bz2 |
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.
Diffstat (limited to 'gdb/mips-tdep.c')
-rw-r--r-- | gdb/mips-tdep.c | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 6277407..976bcf7 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -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; } |