gdb: mips: Fix the handling of complex type of function return value

$ objdump -d outputs/gdb.base/varargs/varargs
00000001200012e8 <find_max_float_real>:
...
   1200013b8:   c7c10000        lwc1    $f1,0(s8)
   1200013bc:   c7c00004        lwc1    $f0,4(s8)
   1200013c0:   46000886        mov.s   $f2,$f1
   1200013c4:   46000046        mov.s   $f1,$f0
   1200013c8:   46001006        mov.s   $f0,$f2
   1200013cc:   46000886        mov.s   $f2,$f1
   1200013d0:   03c0e825        move    sp,s8
   1200013d4:   dfbe0038        ld      s8,56(sp)
   1200013d8:   67bd0080        daddiu  sp,sp,128
   1200013dc:   03e00008        jr      ra
   1200013e0:   00000000        nop

From the above disassembly, we can see that when the return value of the
function is a complex type and len <= 2 * MIPS64_REGSIZE, the return value
will be passed through $f0 and $f2, so fix the corresponding processing
in mips_n32n64_return_value().

$ make check RUNTESTFLAGS='GDB=../gdb gdb.base/varargs.exp --outdir=test'

Before applying the patch:
 FAIL: gdb.base/varargs.exp: print find_max_float_real(4, fc1, fc2, fc3, fc4)
 FAIL: gdb.base/varargs.exp: print find_max_double_real(4, dc1, dc2, dc3, dc4)

 # of expected passes            9
 # of unexpected failures        2

After applying the patch:
 # of expected passes            11

This also fixes:
 FAIL: gdb.base/callfuncs.exp: call inferior func with struct - returns float _Complex

Signed-off-by: Youling Tang <tangyouling@loongson.cn>
Co-Authored-By: Maciej W. Rozycki <macro@orcam.me.uk>
This commit is contained in:
Youling Tang
2022-04-06 23:38:21 +01:00
committed by Maciej W. Rozycki
parent 8fb1059308
commit 089169c003

View File

@ -5217,30 +5217,44 @@ mips_n32n64_return_value (struct gdbarch *gdbarch, struct value *function,
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.] */
registers.]
From MIPSpro Assembly Language Programmer's Guide, Document Number:
007-2418-004
Software
Register Name(from
Name fgregdef.h) Use and Linkage
-----------------------------------------------------------------
$f0, $f2 fv0, fv1 Hold results of floating-point type function
($f0) and complex type function ($f0 has the
real part, $f2 has the imaginary part.) */
if (TYPE_LENGTH (type) > 2 * MIPS64_REGSIZE)
return RETURN_VALUE_STRUCT_CONVENTION;
else if (type->code () == TYPE_CODE_FLT
&& TYPE_LENGTH (type) == 16
else if ((type->code () == TYPE_CODE_COMPLEX
|| (type->code () == TYPE_CODE_FLT && TYPE_LENGTH (type) == 16))
&& tdep->mips_fpu_type != MIPS_FPU_NONE)
{
/* A 128-bit floating-point value fills both $f0 and $f2. The
two registers are used in the same as memory order, so the
eight bytes with the lower memory address are in $f0. */
/* A complex value of up to 128 bits in width as well as a 128-bit
floating-point value goes in both $f0 and $f2. A single complex
value is held in the lower halves only of the respective registers.
The two registers are used in the same as memory order, so the
bytes with the lower memory address are in $f0. */
if (mips_debug)
gdb_printf (gdb_stderr, "Return float in $f0 and $f2\n");
mips_xfer_register (gdbarch, regcache,
(gdbarch_num_regs (gdbarch)
+ mips_regnum (gdbarch)->fp0),
8, gdbarch_byte_order (gdbarch),
TYPE_LENGTH (type) / 2, gdbarch_byte_order (gdbarch),
readbuf, writebuf, 0);
mips_xfer_register (gdbarch, regcache,
(gdbarch_num_regs (gdbarch)
+ mips_regnum (gdbarch)->fp0 + 2),
8, gdbarch_byte_order (gdbarch),
readbuf ? readbuf + 8 : readbuf,
writebuf ? writebuf + 8 : writebuf, 0);
TYPE_LENGTH (type) / 2, gdbarch_byte_order (gdbarch),
readbuf ? readbuf + TYPE_LENGTH (type) / 2 : readbuf,
(writebuf
? writebuf + TYPE_LENGTH (type) / 2 : writebuf), 0);
return RETURN_VALUE_REGISTER_CONVENTION;
}
else if (type->code () == TYPE_CODE_FLT