This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
[RFA] Mips fp register display
- To: gdb-patches at sources dot redhat dot com
- Subject: [RFA] Mips fp register display
- From: Don Howard <dhoward at redhat dot com>
- Date: Thu, 10 May 2001 17:49:45 +0000 (PDT)
I've not received any feedback on the patch included below, so I'm
resubmitting it.
--
-Don
dhoward@redhat.com
gdb engineering
>From dhoward@redhat.com Wed May 9 13:14:49 2001
Date: Tue, 27 Mar 2001 00:53:15 +0000 (PDT)
From: Don Howard <dhoward@redhat.com>
To: gdb-patches@sources.redhat.com
Subject: [RFA] Mips fp register display
This is a patch for an obscure mips fp register display problem: some mips
variants use 2 32 bit float registers to store 64 bit values. gdb does not
display these values correctly.
This patch addresses insight as well as cli gdb. Insight is not 100% correct:
single precision floats are displayed in double format. CLI gdb displays both
float and double. I can change REGISTER_VIRTUAL_TYPE() to try to guess the
the intended type (builtin_type_{float,double}), but that is really not the
right place to fix this problem.
Has anyone considered adding float/double options to the insight register
window format menu? I think that would be the right place to fix this.
2001-03-27 Don Howard <dhoward@redhat.com>
* mips-tdep.c (mips2_read_fp_register): New function. Reads a
64-bit float value stored as two 32-bit fragments in consecutive
float registers.
(mips2_fp_compat): New function. Determine if a MIPS3 or later
cpu is operating in MIPS{1,2} float-compat mode.
(mips_get_saved_register): Modified to use new
mips2-compat float support.
(mips_print_register): Modified to display 64-bit float regs in
single and double precision.
Index: mips-tdep.c
===================================================================
RCS file: /cvs/cvsfiles/devo/gdb/mips-tdep.c,v
retrieving revision 1.239.2.3
diff -p -u -w -r1.239.2.3 mips-tdep.c
--- mips-tdep.c 2001/01/08 16:16:39 1.239.2.3
+++ mips-tdep.c 2001/03/27 08:19:51
@@ -173,6 +173,21 @@ mips_saved_regsize (void)
return 4;
}
+/* Determine if a MIPS3 or later cpu is operating in MIPS{1,2} FPU
+ compatiblitiy mode. */
+
+static int
+mips2_fp_compat (void)
+{
+ if (REGISTER_RAW_SIZE (FP0_REGNUM) != 8) /* MIPS2 has 32 bit fp regs */
+ return 0;
+
+ /* Otherwise check the FR bit in the status register - it controls
+ the fp compatiblity mode */
+ return !(read_register (PS_REGNUM) & 1 << 26);
+}
+
+
/* Indicate that the ABI makes use of double-precision registers
provided by the FPU (rather than combining pairs of registers to
form double-precision values). Do not use "TARGET_IS_MIPS64" to
@@ -2572,6 +2587,58 @@ mips_pop_frame (void)
}
}
+
+/* Read a MIPS{1,2} floating point register. This is for use on MIPS3 or
+ later cpus operating in MIPS2 fpu compatiblity mode.
+
+ Background: MIPS1 & 2 fp registers are 32 bits wide. To support
+ 64bit operations, these early MIPS cpus treat fp register pairs
+ (f0,f1) as a single register (d0). Later MIPS cpu's have 64 bit fp
+ registers and offer a compatibility mode that emulates the MIPS2 fp
+ model. When operating in MIPS2 fp compat mode, later cpu's split
+ double precision floats into two 32-bit chunks and store them in
+ consecutive fp regs. To display 64-bit floats stored in this
+ fashion, we have to combine 32 bits from f0 and 32 bits from f1.
+ Throw in user-configurable endianness and you have a real mess.
+
+ Note that this only deals with "live" registers at the top of the
+ stack. We will attempt to deal with saved registers later, when
+ the raw/cooked register interface is in place. (We need a general
+ interface that can deal with dynamic saved register sizes -- fp
+ regs could be 32 bits wide in one frame and 64 on the frame above
+ and below) */
+
+void
+mips2_read_fp_register (int regno, char * rare_buffer)
+{
+ char * raw_buffer = alloca (REGISTER_RAW_SIZE (FP0_REGNUM));
+ int HI = (TARGET_BYTE_ORDER == BIG_ENDIAN);
+ int LO = (TARGET_BYTE_ORDER != BIG_ENDIAN);
+
+ if (mips_debug)
+ fprintf_unfiltered (gdb_stdlog, "%s(regno=%d, rare_buffer=0x%x) [%s]\n",
+ __FUNCTION__, regno, rare_buffer, (HI ? "BE" : "LE"));
+
+ memset (rare_buffer, 0, REGISTER_RAW_SIZE (FP0_REGNUM));
+
+
+ if ((regno - FP0_REGNUM) & 1)
+ {
+ read_register_gen (regno, raw_buffer);
+ memcpy (&rare_buffer[HI * 4], &raw_buffer[HI * 4], 4);
+ }
+ else
+ {
+ read_register_gen (regno, raw_buffer);
+ memcpy (&rare_buffer[HI * 4], &raw_buffer[HI * 4], 4);
+
+ read_register_gen (regno + 1, raw_buffer);
+ memcpy (&rare_buffer[LO * 4], &raw_buffer[HI * 4], 4);
+ }
+ return;
+}
+
+
static void
mips_print_register (int regnum, int all)
{
@@ -2613,7 +2680,7 @@ mips_print_register (int regnum, int all
/* If virtual format is floating, print it that way. */
if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
- if (FP_REGISTER_DOUBLE)
+ if (FP_REGISTER_DOUBLE || mips2_fp_compat ())
{ /* show 8-byte floats as float AND double: */
int offset = 4 * (TARGET_BYTE_ORDER == BIG_ENDIAN);
@@ -3899,7 +3966,14 @@ mips_get_saved_register (char *raw_buffe
*lval = lval_register;
addr = REGISTER_BYTE (regnum);
if (raw_buffer != NULL)
+ {
+ if (TYPE_CODE_FLT == TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum))
+ && mips2_fp_compat ())
+ mips2_read_fp_register(regnum, raw_buffer);
+
+ else
read_register_gen (regnum, raw_buffer);
+ }
}
if (addrp != NULL)
*addrp = addr;