From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 31734 invoked by alias); 25 Sep 2007 14:50:41 -0000 Received: (qmail 31724 invoked by uid 22791); 25 Sep 2007 14:50:39 -0000 X-Spam-Check-By: sourceware.org Received: from dmz.mips-uk.com (HELO dmz.mips-uk.com) (194.74.144.194) by sourceware.org (qpsmtpd/0.31) with ESMTP; Tue, 25 Sep 2007 14:50:36 +0000 Received: from internal-mx1 ([192.168.192.240] helo=ukservices1.mips.com) by dmz.mips-uk.com with esmtp (Exim 3.35 #1 (Debian)) id 1IaBkA-0003jY-00; Tue, 25 Sep 2007 15:50:34 +0100 Received: from perivale.mips.com ([192.168.192.200]) by ukservices1.mips.com with esmtp (Exim 3.36 #1 (Debian)) id 1IaBk3-0007d8-00; Tue, 25 Sep 2007 15:50:27 +0100 Received: from macro (helo=localhost) by perivale.mips.com with local-esmtp (Exim 4.63) (envelope-from ) id 1IaBk3-0007LY-0m; Tue, 25 Sep 2007 15:50:27 +0100 Date: Tue, 25 Sep 2007 14:50:00 -0000 From: "Maciej W. Rozycki" To: gdb-patches@sourceware.org cc: Daniel Jacobowitz , David Ung , "Maciej W. Rozycki" Subject: mips-tdep.c: Fix new-ABI handling of composite return values Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-MIPS-Technologies-UK-MailScanner: Found to be clean X-MIPS-Technologies-UK-MailScanner-From: macro@mips.com Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-09/txt/msg00349.txt.bz2 Hello, Our current MIPS new-ABI code assumes the return convention for structs and unions is the same as for the old ABI, that is the value is returned via a reference. This is incorrect. Structs that consist of at most two floating point fields are returned in $f0 (and $f2 as required). Any other struct or union of at most 128 bits in size is returned in $2 (and $3 as required). Other composite types are returned via a reference. A longer quotation from the original spec is included with the patch itself. Tested for n32 using the mipsisa32-sde-elf target, with the mips-sim-sde64/-mips64/-EB and mips-sim-sde64/-mips64/-EL boards, fixing 104 regressions (of 189). 2007-09-25 David Ung Maciej W. Rozycki * mips-tdep.c (mips_n32n64_return_value): Per N32/N64 ABI rules return composite types in registers as appropriate. Thanks, Daniel, for your recent fix for C++ pass/return by reference, BTW. With that in place the change below does not trigger a regression in gdb.cp/bs15503.exp that would otherwise start happening. OK to apply? Maciej 12438.diff Index: binutils-quilt/src/gdb/mips-tdep.c =================================================================== --- binutils-quilt.orig/src/gdb/mips-tdep.c 2007-09-25 15:16:29.000000000 +0100 +++ binutils-quilt/src/gdb/mips-tdep.c 2007-09-25 15:17:38.000000000 +0100 @@ -3076,9 +3076,30 @@ gdb_byte *readbuf, const gdb_byte *writebuf) { struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); - if (TYPE_CODE (type) == TYPE_CODE_STRUCT - || TYPE_CODE (type) == TYPE_CODE_UNION - || TYPE_CODE (type) == TYPE_CODE_ARRAY + + /* From MIPSpro N32 ABI Handbook, Document Number: 007-2816-004 + + Function results are returned in $2 (and $3 if needed), or $f0 (and $f2 + if needed), as appropriate for the type. Composite results (struct, + union, or array) are returned in $2/$f0 and $3/$f2 according to the + following rules: + + * A struct with only one or two floating point fields is returned in $f0 + (and $f2 if necessary). This is a generalization of the Fortran COMPLEX + case. + + * Any other struct or union results of at most 128 bits are returned in + $2 (first 64 bits) and $3 (remainder, if necessary). + + * Larger composite results are handled by converting the function to a + procedure with an implicit first parameter, which is a pointer to an area + reserved by the caller to receive the result. [The o32-bit ABI requires + that all composite results be handled by conversion to implicit first + parameters. The MIPS/SGI Fortran implementation has always made a + specific exception to return COMPLEX results in the floating point + registers.] */ + + if (TYPE_CODE (type) == TYPE_CODE_ARRAY || TYPE_LENGTH (type) > 2 * MIPS64_REGSIZE) return RETURN_VALUE_STRUCT_CONVENTION; else if (TYPE_CODE (type) == TYPE_CODE_FLT @@ -3104,10 +3125,10 @@ return RETURN_VALUE_REGISTER_CONVENTION; } else if (TYPE_CODE (type) == TYPE_CODE_FLT + && TYPE_LENGTH (type) <= 8 && tdep->mips_fpu_type != MIPS_FPU_NONE) { - /* A floating-point value belongs in the least significant part - of FP0. */ + /* Single or double floating-point value that fits in FP0. */ if (mips_debug) fprintf_unfiltered (gdb_stderr, "Return float in $fp0\n"); mips_xfer_register (regcache, @@ -3118,16 +3139,55 @@ readbuf, writebuf, 0); return RETURN_VALUE_REGISTER_CONVENTION; } + else if (TYPE_CODE (type) == TYPE_CODE_FLT + && TYPE_LENGTH (type) == 16 + && tdep->mips_fpu_type != MIPS_FPU_NONE) + { + /* A quad-precision floating-point value. The most significant + part goes in FP2, and the least significant in FP0. */ + if (mips_debug) + fprintf_unfiltered (gdb_stderr, "Return float in $fp2/$fp0\n"); + switch (gdbarch_byte_order (current_gdbarch)) + { + case BFD_ENDIAN_LITTLE: + mips_xfer_register (regcache, + gdbarch_num_regs (current_gdbarch) + + mips_regnum (current_gdbarch)->fp0 + 0, + 8, gdbarch_byte_order (current_gdbarch), + readbuf, writebuf, 0); + mips_xfer_register (regcache, + gdbarch_num_regs (current_gdbarch) + + mips_regnum (current_gdbarch)->fp0 + 2, + 8, gdbarch_byte_order (current_gdbarch), + readbuf, writebuf, 8); + break; + case BFD_ENDIAN_BIG: + mips_xfer_register (regcache, + gdbarch_num_regs (current_gdbarch) + + mips_regnum (current_gdbarch)->fp0 + 2, + 8, gdbarch_byte_order (current_gdbarch), + readbuf, writebuf, 0); + mips_xfer_register (regcache, + gdbarch_num_regs (current_gdbarch) + + mips_regnum (current_gdbarch)->fp0 + 0, + 8, gdbarch_byte_order (current_gdbarch), + readbuf, writebuf, 8); + break; + default: + internal_error (__FILE__, __LINE__, "bad switch"); + } + return RETURN_VALUE_REGISTER_CONVENTION; + } else if (TYPE_CODE (type) == TYPE_CODE_STRUCT && TYPE_NFIELDS (type) <= 2 && TYPE_NFIELDS (type) >= 1 && ((TYPE_NFIELDS (type) == 1 - && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) + && (TYPE_CODE (check_typedef (TYPE_FIELD_TYPE (type, 0))) == TYPE_CODE_FLT)) || (TYPE_NFIELDS (type) == 2 - && (TYPE_CODE (TYPE_FIELD_TYPE (type, 0)) + && (TYPE_CODE (check_typedef (TYPE_FIELD_TYPE (type, 0))) == TYPE_CODE_FLT) - && (TYPE_CODE (TYPE_FIELD_TYPE (type, 1)) + && (TYPE_CODE (check_typedef (TYPE_FIELD_TYPE (type, 1))) == TYPE_CODE_FLT))) && tdep->mips_fpu_type != MIPS_FPU_NONE) {