2002-03-10 Daniel Jacobowitz <drow@mvista.com>
Don Howard <dhoward@redhat.com> * mips-tdep.c (ST0_FR): Define. (mips2_fp_compat): New function, temporarily disabled. (mips_read_fp_register_single): New function. (mips_read_fp_register_double): New function. (mips_print_register): Use them. (do_fp_register_row): Likewise.
This commit is contained in:
parent
3029f9b89c
commit
dd824b049b
|
@ -1,3 +1,13 @@
|
||||||
|
2002-03-10 Daniel Jacobowitz <drow@mvista.com>
|
||||||
|
Don Howard <dhoward@redhat.com>
|
||||||
|
|
||||||
|
* mips-tdep.c (ST0_FR): Define.
|
||||||
|
(mips2_fp_compat): New function, temporarily disabled.
|
||||||
|
(mips_read_fp_register_single): New function.
|
||||||
|
(mips_read_fp_register_double): New function.
|
||||||
|
(mips_print_register): Use them.
|
||||||
|
(do_fp_register_row): Likewise.
|
||||||
|
|
||||||
2002-03-09 Andrew Cagney <ac131313@redhat.com>
|
2002-03-09 Andrew Cagney <ac131313@redhat.com>
|
||||||
|
|
||||||
* MAINTAINERS: Add Jim Ingham and Klee Dienes to ``write after
|
* MAINTAINERS: Add Jim Ingham and Klee Dienes to ``write after
|
||||||
|
|
207
gdb/mips-tdep.c
207
gdb/mips-tdep.c
|
@ -44,6 +44,10 @@
|
||||||
#include "elf-bfd.h"
|
#include "elf-bfd.h"
|
||||||
#include "symcat.h"
|
#include "symcat.h"
|
||||||
|
|
||||||
|
/* A useful bit in the CP0 status register (PS_REGNUM). */
|
||||||
|
/* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip. */
|
||||||
|
#define ST0_FR (1 << 26)
|
||||||
|
|
||||||
/* The sizes of floating point registers. */
|
/* The sizes of floating point registers. */
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
@ -174,6 +178,31 @@ mips_saved_regsize (void)
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Determine if a MIPS3 or later cpu is operating in MIPS{1,2} FPU
|
||||||
|
compatiblity mode. A return value of 1 means that we have
|
||||||
|
physical 64-bit registers, but should treat them as 32-bit registers. */
|
||||||
|
|
||||||
|
static int
|
||||||
|
mips2_fp_compat (void)
|
||||||
|
{
|
||||||
|
/* MIPS1 and MIPS2 have only 32 bit FPRs, and the FR bit is not
|
||||||
|
meaningful. */
|
||||||
|
if (REGISTER_RAW_SIZE (FP0_REGNUM) == 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
|
||||||
|
the FP compatiblity mode. If it is clear we are in compatibility
|
||||||
|
mode. */
|
||||||
|
if ((read_register (PS_REGNUM) & ST0_FR) == 0)
|
||||||
|
return 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Indicate that the ABI makes use of double-precision registers
|
/* Indicate that the ABI makes use of double-precision registers
|
||||||
provided by the FPU (rather than combining pairs of registers to
|
provided by the FPU (rather than combining pairs of registers to
|
||||||
form double-precision values). Do not use "TARGET_IS_MIPS64" to
|
form double-precision values). Do not use "TARGET_IS_MIPS64" to
|
||||||
|
@ -257,6 +286,9 @@ find_proc_desc (CORE_ADDR pc, struct frame_info *next_frame, int cur_frame);
|
||||||
static CORE_ADDR after_prologue (CORE_ADDR pc,
|
static CORE_ADDR after_prologue (CORE_ADDR pc,
|
||||||
mips_extra_func_info_t proc_desc);
|
mips_extra_func_info_t proc_desc);
|
||||||
|
|
||||||
|
static void mips_read_fp_register_single (int regno, char *rare_buffer);
|
||||||
|
static void mips_read_fp_register_double (int regno, char *rare_buffer);
|
||||||
|
|
||||||
/* This value is the model of MIPS in use. It is derived from the value
|
/* This value is the model of MIPS in use. It is derived from the value
|
||||||
of the PrID register. */
|
of the PrID register. */
|
||||||
|
|
||||||
|
@ -2676,6 +2708,104 @@ mips_pop_frame (void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Floating point register management.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
The way this works is:
|
||||||
|
- If we are in 32-bit mode or on a 32-bit processor, then a 64-bit
|
||||||
|
double-precision value will be split across two logical registers.
|
||||||
|
The lower-numbered logical register will hold the low-order bits,
|
||||||
|
regardless of the processor's endianness.
|
||||||
|
- If we are on a 64-bit processor, and we are looking for a
|
||||||
|
single-precision value, it will be in the low ordered bits
|
||||||
|
of a 64-bit GPR (after mfc1, for example) or a 64-bit register
|
||||||
|
save slot in memory.
|
||||||
|
- If we are in 64-bit mode, everything is straightforward.
|
||||||
|
|
||||||
|
Note that this code 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). */
|
||||||
|
|
||||||
|
/* Copy a 32-bit single-precision value from the current frame
|
||||||
|
into rare_buffer. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
mips_read_fp_register_single (int regno, char *rare_buffer)
|
||||||
|
{
|
||||||
|
int raw_size = REGISTER_RAW_SIZE (regno);
|
||||||
|
char *raw_buffer = alloca (raw_size);
|
||||||
|
|
||||||
|
if (read_relative_register_raw_bytes (regno, raw_buffer))
|
||||||
|
error ("can't read register %d (%s)", regno, REGISTER_NAME (regno));
|
||||||
|
if (raw_size == 8)
|
||||||
|
{
|
||||||
|
/* We have a 64-bit value for this register. Find the low-order
|
||||||
|
32 bits. */
|
||||||
|
int offset;
|
||||||
|
|
||||||
|
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
|
||||||
|
offset = 4;
|
||||||
|
else
|
||||||
|
offset = 0;
|
||||||
|
|
||||||
|
memcpy (rare_buffer, raw_buffer + offset, 4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy (rare_buffer, raw_buffer, 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Copy a 64-bit double-precision value from the current frame into
|
||||||
|
rare_buffer. This may include getting half of it from the next
|
||||||
|
register. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
mips_read_fp_register_double (int regno, char *rare_buffer)
|
||||||
|
{
|
||||||
|
int raw_size = REGISTER_RAW_SIZE (regno);
|
||||||
|
|
||||||
|
if (raw_size == 8 && !mips2_fp_compat ())
|
||||||
|
{
|
||||||
|
/* We have a 64-bit value for this register, and we should use
|
||||||
|
all 64 bits. */
|
||||||
|
if (read_relative_register_raw_bytes (regno, rare_buffer))
|
||||||
|
error ("can't read register %d (%s)", regno, REGISTER_NAME (regno));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((regno - FP0_REGNUM) & 1)
|
||||||
|
internal_error (__FILE__, __LINE__,
|
||||||
|
"mips_read_fp_register_double: bad access to "
|
||||||
|
"odd-numbered FP register");
|
||||||
|
|
||||||
|
/* mips_read_fp_register_single will find the correct 32 bits from
|
||||||
|
each register. */
|
||||||
|
if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
|
||||||
|
{
|
||||||
|
mips_read_fp_register_single (regno, rare_buffer + 4);
|
||||||
|
mips_read_fp_register_single (regno + 1, rare_buffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mips_read_fp_register_single (regno, rare_buffer);
|
||||||
|
mips_read_fp_register_single (regno + 1, rare_buffer + 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mips_print_register (int regnum, int all)
|
mips_print_register (int regnum, int all)
|
||||||
{
|
{
|
||||||
|
@ -2688,22 +2818,23 @@ mips_print_register (int regnum, int all)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If an even floating point register, also print as double. */
|
/* If we have a actual 32-bit floating point register (or we are in
|
||||||
|
32-bit compatibility mode), and the register is even-numbered,
|
||||||
|
also print it as a double (spanning two registers). */
|
||||||
if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT
|
if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT
|
||||||
|
&& (REGISTER_RAW_SIZE (regnum) == 4
|
||||||
|
|| mips2_fp_compat ())
|
||||||
&& !((regnum - FP0_REGNUM) & 1))
|
&& !((regnum - FP0_REGNUM) & 1))
|
||||||
if (REGISTER_RAW_SIZE (regnum) == 4) /* this would be silly on MIPS64 or N32 (Irix 6) */
|
{
|
||||||
{
|
char dbuffer[2 * MAX_REGISTER_RAW_SIZE];
|
||||||
char dbuffer[2 * MAX_REGISTER_RAW_SIZE];
|
|
||||||
|
|
||||||
read_relative_register_raw_bytes (regnum, dbuffer);
|
mips_read_fp_register_double (regnum, dbuffer);
|
||||||
read_relative_register_raw_bytes (regnum + 1, dbuffer + MIPS_REGSIZE);
|
|
||||||
REGISTER_CONVERT_TO_TYPE (regnum, builtin_type_double, dbuffer);
|
|
||||||
|
|
||||||
printf_filtered ("(d%d: ", regnum - FP0_REGNUM);
|
printf_filtered ("(d%d: ", regnum - FP0_REGNUM);
|
||||||
val_print (builtin_type_double, dbuffer, 0, 0,
|
val_print (builtin_type_double, dbuffer, 0, 0,
|
||||||
gdb_stdout, 0, 1, 0, Val_pretty_default);
|
gdb_stdout, 0, 1, 0, Val_pretty_default);
|
||||||
printf_filtered ("); ");
|
printf_filtered ("); ");
|
||||||
}
|
}
|
||||||
fputs_filtered (REGISTER_NAME (regnum), gdb_stdout);
|
fputs_filtered (REGISTER_NAME (regnum), gdb_stdout);
|
||||||
|
|
||||||
/* The problem with printing numeric register names (r26, etc.) is that
|
/* The problem with printing numeric register names (r26, etc.) is that
|
||||||
|
@ -2717,8 +2848,10 @@ mips_print_register (int regnum, int all)
|
||||||
|
|
||||||
/* If virtual format is floating, print it that way. */
|
/* If virtual format is floating, print it that way. */
|
||||||
if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
|
if (TYPE_CODE (REGISTER_VIRTUAL_TYPE (regnum)) == TYPE_CODE_FLT)
|
||||||
if (FP_REGISTER_DOUBLE)
|
if (REGISTER_RAW_SIZE (regnum) == 8 && !mips2_fp_compat ())
|
||||||
{ /* show 8-byte floats as float AND double: */
|
{
|
||||||
|
/* We have a meaningful 64-bit value in this register. Show
|
||||||
|
it as a 32-bit float and a 64-bit double. */
|
||||||
int offset = 4 * (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
|
int offset = 4 * (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
|
||||||
|
|
||||||
printf_filtered (" (float) ");
|
printf_filtered (" (float) ");
|
||||||
|
@ -2753,34 +2886,24 @@ mips_print_register (int regnum, int all)
|
||||||
static int
|
static int
|
||||||
do_fp_register_row (int regnum)
|
do_fp_register_row (int regnum)
|
||||||
{ /* do values for FP (float) regs */
|
{ /* do values for FP (float) regs */
|
||||||
char *raw_buffer[2];
|
char *raw_buffer;
|
||||||
char *dbl_buffer;
|
|
||||||
/* use HI and LO to control the order of combining two flt regs */
|
|
||||||
int HI = (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
|
|
||||||
int LO = (TARGET_BYTE_ORDER != BFD_ENDIAN_BIG);
|
|
||||||
double doub, flt1, flt2; /* doubles extracted from raw hex data */
|
double doub, flt1, flt2; /* doubles extracted from raw hex data */
|
||||||
int inv1, inv2, inv3;
|
int inv1, inv2, inv3;
|
||||||
|
|
||||||
raw_buffer[0] = (char *) alloca (REGISTER_RAW_SIZE (FP0_REGNUM));
|
raw_buffer = (char *) alloca (2 * REGISTER_RAW_SIZE (FP0_REGNUM));
|
||||||
raw_buffer[1] = (char *) alloca (REGISTER_RAW_SIZE (FP0_REGNUM));
|
|
||||||
dbl_buffer = (char *) alloca (2 * REGISTER_RAW_SIZE (FP0_REGNUM));
|
|
||||||
|
|
||||||
/* Get the data in raw format. */
|
if (REGISTER_RAW_SIZE (regnum) == 4 || mips2_fp_compat ())
|
||||||
if (read_relative_register_raw_bytes (regnum, raw_buffer[HI]))
|
|
||||||
error ("can't read register %d (%s)", regnum, REGISTER_NAME (regnum));
|
|
||||||
if (REGISTER_RAW_SIZE (regnum) == 4)
|
|
||||||
{
|
{
|
||||||
/* 4-byte registers: we can fit two registers per row. */
|
/* 4-byte registers: we can fit two registers per row. */
|
||||||
/* Also print every pair of 4-byte regs as an 8-byte double. */
|
/* Also print every pair of 4-byte regs as an 8-byte double. */
|
||||||
if (read_relative_register_raw_bytes (regnum + 1, raw_buffer[LO]))
|
mips_read_fp_register_single (regnum, raw_buffer);
|
||||||
error ("can't read register %d (%s)",
|
flt1 = unpack_double (builtin_type_float, raw_buffer, &inv1);
|
||||||
regnum + 1, REGISTER_NAME (regnum + 1));
|
|
||||||
|
|
||||||
/* copy the two floats into one double, and unpack both */
|
mips_read_fp_register_single (regnum + 1, raw_buffer);
|
||||||
memcpy (dbl_buffer, raw_buffer, 2 * REGISTER_RAW_SIZE (FP0_REGNUM));
|
flt2 = unpack_double (builtin_type_float, raw_buffer, &inv2);
|
||||||
flt1 = unpack_double (builtin_type_float, raw_buffer[HI], &inv1);
|
|
||||||
flt2 = unpack_double (builtin_type_float, raw_buffer[LO], &inv2);
|
mips_read_fp_register_double (regnum, raw_buffer);
|
||||||
doub = unpack_double (builtin_type_double, dbl_buffer, &inv3);
|
doub = unpack_double (builtin_type_double, raw_buffer, &inv3);
|
||||||
|
|
||||||
printf_filtered (" %-5s", REGISTER_NAME (regnum));
|
printf_filtered (" %-5s", REGISTER_NAME (regnum));
|
||||||
if (inv1)
|
if (inv1)
|
||||||
|
@ -2805,13 +2928,13 @@ do_fp_register_row (int regnum)
|
||||||
regnum += 2;
|
regnum += 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{ /* eight byte registers: print each one as float AND as double. */
|
{
|
||||||
int offset = 4 * (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG);
|
/* Eight byte registers: print each one as float AND as double. */
|
||||||
|
mips_read_fp_register_single (regnum, raw_buffer);
|
||||||
|
flt1 = unpack_double (builtin_type_double, raw_buffer, &inv1);
|
||||||
|
|
||||||
memcpy (dbl_buffer, raw_buffer[HI], 2 * REGISTER_RAW_SIZE (FP0_REGNUM));
|
mips_read_fp_register_double (regnum, raw_buffer);
|
||||||
flt1 = unpack_double (builtin_type_float,
|
doub = unpack_double (builtin_type_double, raw_buffer, &inv3);
|
||||||
&raw_buffer[HI][offset], &inv1);
|
|
||||||
doub = unpack_double (builtin_type_double, dbl_buffer, &inv3);
|
|
||||||
|
|
||||||
printf_filtered (" %-5s: ", REGISTER_NAME (regnum));
|
printf_filtered (" %-5s: ", REGISTER_NAME (regnum));
|
||||||
if (inv1)
|
if (inv1)
|
||||||
|
|
Loading…
Reference in New Issue