From 609ba7801aaaa100fd380f64442004426cd2976b Mon Sep 17 00:00:00 2001 From: Joseph Myers Date: Tue, 3 Jun 2008 10:53:34 +0000 Subject: [PATCH] 2008-06-03 Michael Snyder Joseph Myers * mips-tdep.c (mips_eabi_return_value): Replace stub that always returned RETURN_VALUE_STRUCT_CONVENTION with a real function. --- gdb/ChangeLog | 6 ++++++ gdb/mips-tdep.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 08a01c742e5..5f4fbba5f9b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2008-06-03 Michael Snyder + Joseph Myers + + * 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 * m68klinux-tdep.c (m68k_linux_pc_in_sigtramp): Fix incorrect test. diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 6277407695d..976bcf7f0e6 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; } -- 2.30.2