This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
mips-tdep.c: Unification of FPR size detection
- From: "Maciej W. Rozycki" <macro at mips dot com>
- To: gdb-patches at sourceware dot org
- Cc: Nigel Stephens <nigel at mips dot com>, David Ung <davidu at mips dot com>, "Maciej W. Rozycki" <macro at linux-mips dot org>
- Date: Wed, 21 Nov 2007 17:40:28 +0000 (GMT)
- Subject: mips-tdep.c: Unification of FPR size detection
Hello,
This is a set of changes to put code to determine the width of floating
point registers into a single place. This is required for the support for
MIPS32r2 64-bit FPRs to be added in a sensible way.
I think the changes are mostly obvious. If not, then please enquire.
Modifications to mips_o32_return_value(), mips_o32_push_dummy_call() and
mips_register_type() change the semantics somewhat, but this is correct as
for 64-bit processors in the compatibility mode FPRs are seen as 32-bit.
The rest just shuffles code for consistency.
One note: the mips2_fp_compat() function is meant to detect the size of
floating point registers based on the setting of the cp0.Status.FR bit as
applicable. However the function currently always returns 0. So I
decided to include a change that ifdefs out the entire body. Enabling the
body does not trigger any new regressions. I also added a note on a
problem with the frame being NULL -- it may have to be dealt with in a
better way once this code is reenabled. A possible way is by caching the
value of cp0.Status.FR elsewhere.
Tested for using the mipsisa32-sde-elf target, with the
mips-sim-sde32/-EB, mips-sim-sde32/-EL, mips-sim-sde64/-mips64/-EB and
mips-sim-sde64/-mips64/-EL boards with no regressions.
2007-11-21 Nigel Stephens <nigel@mips.com>
David Ung <davidu@mips.com>
Maciej W. Rozycki <macro@mips.com>
* mips-tdep.c (mips_float_register_p): New function.
(mips_float_regsize): Likewise.
(mips2_fp_compat): Handle a NULL pointer possibly passed. Ifdef
out pointless code.
(mips_convert_register_p): Use mips_float_register_p().
(mips_register_type): Likewise. Use mips_float_regsize()
instead of mips_isa_regsize() for FP registers.
(mips_o32_push_dummy_call): Use mips_float_regsize() instead of
register_size() for FP registers.
(mips_print_fp_register): Likewise.
(mips_print_register): Likewise.
(print_gp_register_row): Likewise.
(mips_o32_return_value): Use mips_float_regsize() instead of
hardcoding the expected width of FP registers.
OK to apply?
Maciej
14440-2.diff
Index: binutils-quilt/src/gdb/mips-tdep.c
===================================================================
--- binutils-quilt.orig/src/gdb/mips-tdep.c 2007-11-21 11:37:00.000000000 +0000
+++ binutils-quilt/src/gdb/mips-tdep.c 2007-11-21 11:47:35.000000000 +0000
@@ -62,6 +62,8 @@
static struct type *mips_register_type (struct gdbarch *gdbarch, int regnum);
+static int mips2_fp_compat (struct frame_info *frame);
+
/* A useful bit in the CP0 status register (MIPS_PS_REGNUM). */
/* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip. */
#define ST0_FR (1 << 26)
@@ -211,6 +213,24 @@
return mips_regnum (gdbarch)->fp0 + 12;
}
+static int
+mips_float_register_p (struct gdbarch *gdbarch, int regnum)
+{
+ return ((regnum % gdbarch_num_regs (gdbarch))
+ >= mips_regnum (gdbarch)->fp0
+ && (regnum % gdbarch_num_regs (gdbarch))
+ < mips_regnum (gdbarch)->fp0 + 32);
+}
+
+static int
+mips_float_regsize (struct gdbarch *gdbarch, struct frame_info *frame)
+{
+ if (mips_isa_regsize (gdbarch) == 8 && ! mips2_fp_compat (frame))
+ /* 64-bit ISA with 32-bit compatibility mode FPU. */
+ return 8;
+ return 4;
+}
+
#define MIPS_EABI (gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI32 \
|| gdbarch_tdep (current_gdbarch)->mips_abi == MIPS_ABI_EABI64)
@@ -370,13 +390,21 @@
static int
mips2_fp_compat (struct frame_info *frame)
{
- struct gdbarch *gdbarch = get_frame_arch (frame);
+#if 0
+ struct gdbarch *gdbarch;
+
+ /* FIXME macro 2007-11-15: If we have no frame, then we cannot really
+ get it or gdbarch_data() will be called recursively (through
+ data->post_init()). Assume the native size. */
+ if (frame == NULL)
+ return 0;
+ gdbarch = get_frame_arch (frame);
+
/* MIPS1 and MIPS2 have only 32 bit FPRs, and the FR bit is not
meaningful. */
if (register_size (gdbarch, mips_regnum (gdbarch)->fp0) == 4)
return 0;
-#if 0
/* FIXME drow 2002-03-10: This is disabled until we can do it consistently,
in all the places we deal with FP registers. PR gdb/413. */
/* Otherwise check the FR bit in the status register - it controls
@@ -664,10 +692,7 @@
{
return (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG
&& register_size (gdbarch, regnum) == 4
- && (regnum % gdbarch_num_regs (gdbarch))
- >= mips_regnum (gdbarch)->fp0
- && (regnum % gdbarch_num_regs (gdbarch))
- < mips_regnum (gdbarch)->fp0 + 32
+ && mips_float_register_p (gdbarch, regnum)
&& TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8);
}
@@ -694,13 +719,11 @@
mips_register_type (struct gdbarch *gdbarch, int regnum)
{
gdb_assert (regnum >= 0 && regnum < 2 * gdbarch_num_regs (gdbarch));
- if ((regnum % gdbarch_num_regs (gdbarch)) >= mips_regnum (gdbarch)->fp0
- && (regnum % gdbarch_num_regs (gdbarch))
- < mips_regnum (gdbarch)->fp0 + 32)
+ if (mips_float_register_p (gdbarch, regnum))
{
/* The floating-point registers raw, or cooked, always match
mips_isa_regsize(), and also map 1:1, byte for byte. */
- if (mips_isa_regsize (gdbarch) == 4)
+ if (mips_float_regsize (gdbarch, NULL) == 4)
return builtin_type_ieee_single;
else
return builtin_type_ieee_double;
@@ -3512,7 +3535,7 @@
if (fp_register_arg_p (typecode, arg_type)
&& float_argreg <= MIPS_LAST_FP_ARG_REGNUM)
{
- if (register_size (gdbarch, float_argreg) < 8 && len == 8)
+ if (mips_float_regsize (gdbarch, NULL) < 8 && len == 8)
{
int low_offset = gdbarch_byte_order (gdbarch)
== BFD_ENDIAN_BIG ? 4 : 0;
@@ -3721,7 +3744,8 @@
|| TYPE_CODE (type) == TYPE_CODE_ARRAY)
return RETURN_VALUE_STRUCT_CONVENTION;
else if (TYPE_CODE (type) == TYPE_CODE_FLT
- && TYPE_LENGTH (type) == 4 && tdep->mips_fpu_type != MIPS_FPU_NONE)
+ && TYPE_LENGTH (type) <= mips_float_regsize (gdbarch, NULL)
+ && tdep->mips_fpu_type != MIPS_FPU_NONE)
{
/* A single-precision floating-point value. It fits in the
least significant part of FP0. */
@@ -4275,14 +4299,14 @@
double doub, flt1; /* doubles extracted from raw hex data */
int inv1, inv2;
- raw_buffer = alloca (2 * register_size (gdbarch, mips_regnum (gdbarch)->fp0));
+ raw_buffer = alloca (2 * mips_float_regsize (gdbarch, frame));
fprintf_filtered (file, "%s:", gdbarch_register_name (gdbarch, regnum));
fprintf_filtered (file, "%*s",
4 - (int) strlen (gdbarch_register_name (gdbarch, regnum)),
"");
- if (register_size (gdbarch, regnum) == 4 || mips2_fp_compat (frame))
+ if (mips_float_regsize (gdbarch, frame) == 4)
{
/* 4-byte registers: Print hex and floating. Also print even
numbered registers as doubles. */
@@ -4346,7 +4370,7 @@
gdb_byte raw_buffer[MAX_REGISTER_SIZE];
int offset;
- if (TYPE_CODE (register_type (gdbarch, regnum)) == TYPE_CODE_FLT)
+ if (mips_float_register_p (gdbarch, regnum))
{
mips_print_fp_register (file, frame, regnum);
return;
@@ -4417,8 +4441,7 @@
{
if (*gdbarch_register_name (gdbarch, regnum) == '\0')
continue; /* unused register */
- if (TYPE_CODE (register_type (gdbarch, regnum)) ==
- TYPE_CODE_FLT)
+ if (mips_float_register_p (gdbarch, regnum))
break; /* end the row: reached FP register */
/* Large registers are handled separately. */
if (register_size (gdbarch, regnum) > mips_abi_regsize (gdbarch))
@@ -4457,8 +4480,7 @@
{
if (*gdbarch_register_name (gdbarch, regnum) == '\0')
continue; /* unused register */
- if (TYPE_CODE (register_type (gdbarch, regnum)) ==
- TYPE_CODE_FLT)
+ if (mips_float_register_p (gdbarch, regnum))
break; /* end row: reached FP register */
if (register_size (gdbarch, regnum) > mips_abi_regsize (gdbarch))
break; /* End row: large register. */
@@ -4513,8 +4535,7 @@
while (regnum < gdbarch_num_regs (gdbarch)
+ gdbarch_num_pseudo_regs (gdbarch))
{
- if (TYPE_CODE (register_type (gdbarch, regnum)) ==
- TYPE_CODE_FLT)
+ if (mips_float_register_p (gdbarch, regnum))
{
if (all) /* true for "INFO ALL-REGISTERS" command */
regnum = print_fp_register_row (file, frame, regnum);