From mboxrd@z Thu Jan 1 00:00:00 1970 From: Don Howard To: Subject: [RFA] mips fp register display Date: Thu, 21 Jun 2001 14:41:00 -0000 Message-id: X-SW-Source: 2001-06/msg00374.html This is a patch for an obscure mips fp register display problem. 32 bit mips chips support 64 bit float operations using two fp registers. 64 bit mips chips provide a backward compatiblity mode where 64 bit float ops are also supported using 2 float regsiters -- 32 bits stored in each of the 2 64bit fp regs. 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. 2001-06-21 Don Howard * 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/src/src/gdb/mips-tdep.c,v retrieving revision 1.54 diff -p -u -w -r1.54 mips-tdep.c --- mips-tdep.c 2001/06/16 20:00:24 1.54 +++ mips-tdep.c 2001/06/21 21:25:48 @@ -174,6 +174,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,63 @@ 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) + { + /* Odd numbered registers are the lower half of a 64 bit value, + when in mips2 compat mode. We print them out here just as an + attempt to do something useful. Note also that rare_buffer + has been memset to 0. */ + 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 +2685,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); @@ -3819,7 +3891,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; -- -Don dhoward@redhat.com gdb engineering