public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 3/3] MIPS: Provide FPU info and decode FCSR in `info float'
  2014-12-17  6:46 [PATCH 0/3, V2] MIPS: Provide FPU info and decode FCSR in `info float' Yao Qi
  2014-12-17  6:46 ` [PATCH 1/3] Remove h8300_print_float_info Yao Qi
@ 2014-12-17  6:46 ` Yao Qi
  2014-12-17 10:53   ` Pedro Alves
  2014-12-17  6:46 ` [PATCH 2/3] Refactor gdbarch method print_float_info Yao Qi
  2014-12-18 12:52 ` [PATCH 0/3, V2] MIPS: Provide FPU info and decode FCSR in `info float' Yao Qi
  3 siblings, 1 reply; 13+ messages in thread
From: Yao Qi @ 2014-12-17  6:46 UTC (permalink / raw)
  To: gdb-patches

This patch is the V2.  V1 can be found in
https://sourceware.org/ml/gdb-patches/2012-05/msg00938.html
V2 is to address Joel's comment
<https://sourceware.org/ml/gdb-patches/2012-06/msg00289.html> about
keeping dumping floating point registers.  Additionally, command
'info float' prints bits on nan2008 and abs2008.

------------------------------------------------------------------

 The change below provides a MIPS-specific handler for the:

(gdb) info float

command.  It provides information about the FPU type available (if any),
the FPU register width, and decodes the CP1 Floating Point Control and
Status Register (FCSR):

(gdb) print /x $fsr
$1 = 0xff83ffff
(gdb) info float
fpu type: double-precision
reg size: 32 bits
cond    : 0 1 2 3 4 5 6 7
cause   : inexact uflow oflow div0 inval unimp
mask    : inexact uflow oflow div0 inval
flags   : inexact uflow oflow div0 inval
rounding: -inf
flush   : zero

 One point to note about CP1.FCSR are the non-standard Flush-to-Nearest
and Flush-Override bits.  They are not a part of the MIPS architecture and
take two positions reserved for an implementation-dependent use in the
architecture.  They are present in all the FPU implementations made by
MIPS Technologies since the spin-off from SGI.

 I haven't been able to track down a single other MIPS FPU implementation
that would make any use of these bits and they are required to be
hardwired to zero by the architecture specification if unimplemented.
Therefore I think it makes sense to report them in the current way.

 GDB has no guaranteed access to the CP0 Processor Identification (PRId)
register to validate this feature properly and the ID information stored
in the CP1 Floating Point Implementation Register (FIR) is from my
experience not reliable enough (there's no Company ID available there for
once unlike in CP0.PRId and Processor ID is not guaranteed to be unique).

 As a side note we should probably dump CP1.FIR information as well, as
there's useful stuff indicating some FPU features there.  That's material
for another change however.

gdb/

2014-12-17  Nigel Stephens  <nigel@mips.com>
            Maciej W. Rozycki  <macro@codesourcery.com>

	* mips-tdep.c (print_fpu_flags): New function.
	(mips_print_float_info): Likewise.
	(mips_gdbarch_init): Install mips_print_float_info as gdbarch
	print_float_info routine.

gdb/testsuite/

2014-12-17  Nigel Stephens  <nigel@mips.com>
            Maciej W. Rozycki  <macro@codesourcery.com>

	* gdb.base/float.exp: Handle the new output from "info float" on
	MIPS targets.
---
 gdb/mips-tdep.c                  | 95 ++++++++++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/float.exp |  9 +++-
 2 files changed, 103 insertions(+), 1 deletion(-)

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index eb99910..d528969 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -73,6 +73,9 @@ static int micromips_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
 static int mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
 					     CORE_ADDR addr, int mustbe32);
 
+static void mips_print_float_info (struct gdbarch *, struct ui_file *,
+				   struct frame_info *, const char *);
+
 /* 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)
@@ -6387,6 +6390,96 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
 			      &opts, 0, file);
 }
 
+/* Print IEEE exception condition bits in FLAGS.  */
+
+static void
+print_fpu_flags (struct ui_file *file, int flags)
+{
+  if (flags & (1 << 0))
+    fputs_filtered (" inexact", file);
+  if (flags & (1 << 1))
+    fputs_filtered (" uflow", file);
+  if (flags & (1 << 2))
+    fputs_filtered (" oflow", file);
+  if (flags & (1 << 3))
+    fputs_filtered (" div0", file);
+  if (flags & (1 << 4))
+    fputs_filtered (" inval", file);
+  if (flags & (1 << 5))
+    fputs_filtered (" unimp", file);
+  fputc_filtered ('\n', file);
+}
+
+/* Print interesting information about the floating point processor
+   (if present) or emulator.  */
+
+static void
+mips_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
+		      struct frame_info *frame, const char *args)
+{
+  int fcsr = mips_regnum (gdbarch)->fp_control_status;
+  enum mips_fpu_type type = MIPS_FPU_TYPE (gdbarch);
+  ULONGEST fcs = 0;
+  int i;
+
+  if (fcsr == -1 || !deprecated_frame_register_read (frame, fcsr, NULL))
+    type = MIPS_FPU_NONE;
+
+  fprintf_filtered (file, "fpu type: %s\n",
+		    type == MIPS_FPU_DOUBLE ? "double-precision"
+		    : type == MIPS_FPU_SINGLE ? "single-precision"
+		    : "none / unused");
+
+  if (type == MIPS_FPU_NONE)
+    return;
+
+  fprintf_filtered (file, "reg size: %d bits\n",
+		    register_size (gdbarch, mips_regnum (gdbarch)->fp0) * 8);
+
+  fcs = get_frame_register_unsigned (frame, fcsr);
+
+  fputs_filtered ("cond    :", file);
+  if (fcs & (1 << 23))
+    fputs_filtered (" 0", file);
+  for (i = 1; i <= 7; i++)
+    if (fcs & (1 << (24 + i)))
+      fprintf_filtered (file, " %d", i);
+  fputc_filtered ('\n', file);
+
+  fputs_filtered ("cause   :", file);
+  print_fpu_flags (file, (fcs >> 12) & 0x3f);
+  fputs ("mask    :", stdout);
+  print_fpu_flags (file, (fcs >> 7) & 0x1f);
+  fputs ("flags   :", stdout);
+  print_fpu_flags (file, (fcs >> 2) & 0x1f);
+
+  fputs_filtered ("rounding: ", file);
+  switch (fcs & 3)
+    {
+    case 0: fputs_filtered ("nearest\n", file); break;
+    case 1: fputs_filtered ("zero\n", file); break;
+    case 2: fputs_filtered ("+inf\n", file); break;
+    case 3: fputs_filtered ("-inf\n", file); break;
+    }
+
+  fputs_filtered ("flush   :", file);
+  if (fcs & (1 << 21))
+    fputs_filtered (" nearest", file);
+  if (fcs & (1 << 22))
+    fputs_filtered (" override", file);
+  if (fcs & (1 << 24))
+    fputs_filtered (" zero", file);
+  if ((fcs & (0xb << 21)) == 0)
+    fputs_filtered (" no", file);
+  fputc_filtered ('\n', file);
+
+  fprintf_filtered (file, "nan2008 : %s\n", fcs & (1 << 18) ? "yes" : "no");
+  fprintf_filtered (file, "abs2008 : %s\n", fcs & (1 << 19) ? "yes" : "no");
+  fputc_filtered ('\n', file);
+
+  default_print_float_info (gdbarch, file, frame, args);
+}
+
 /* Replacement for generic do_registers_info.
    Print regs in pretty columns.  */
 
@@ -8737,6 +8830,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_push_dummy_code (gdbarch, mips_push_dummy_code);
   set_gdbarch_frame_align (gdbarch, mips_frame_align);
 
+  set_gdbarch_print_float_info (gdbarch, mips_print_float_info);
+
   set_gdbarch_convert_register_p (gdbarch, mips_convert_register_p);
   set_gdbarch_register_to_value (gdbarch, mips_register_to_value);
   set_gdbarch_value_to_register (gdbarch, mips_value_to_register);
diff --git a/gdb/testsuite/gdb.base/float.exp b/gdb/testsuite/gdb.base/float.exp
index 5da9630..3ecb01b 100644
--- a/gdb/testsuite/gdb.base/float.exp
+++ b/gdb/testsuite/gdb.base/float.exp
@@ -68,7 +68,14 @@ if { [istarget "aarch64*-*-*"] } then {
 	}
     }
 } elseif [istarget "mips*-*-*"] then {
-    gdb_test "info float" "f0:.*flt:.*dbl:.*" "info float"
+    gdb_test_multiple "info float" "info float" {
+	-re "fpu type: none*" {
+	      pass "info float (without FPU)"
+	  }
+	-re "fpu type:.*cause.*mask.*flags.*round.*flush.*" {
+	      pass "info float (with FPU)"
+	  }
+    }
 } elseif [istarget "powerpc*-*-*"] then {
     gdb_test_multiple "info float" "info_float" {
         -re "f0.*f1.*f31.*fpscr.*$gdb_prompt $" {
-- 
1.9.3

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 2/3] Refactor gdbarch method print_float_info
  2014-12-17  6:46 [PATCH 0/3, V2] MIPS: Provide FPU info and decode FCSR in `info float' Yao Qi
  2014-12-17  6:46 ` [PATCH 1/3] Remove h8300_print_float_info Yao Qi
  2014-12-17  6:46 ` [PATCH 3/3] MIPS: Provide FPU info and decode FCSR in `info float' Yao Qi
@ 2014-12-17  6:46 ` Yao Qi
  2014-12-17 13:24   ` Pedro Alves
  2014-12-18 12:52 ` [PATCH 0/3, V2] MIPS: Provide FPU info and decode FCSR in `info float' Yao Qi
  3 siblings, 1 reply; 13+ messages in thread
From: Yao Qi @ 2014-12-17  6:46 UTC (permalink / raw)
  To: gdb-patches

This patch is to change print_float_info gdbarch method for the
following two reasons,

 1. we want to add a default implementation of print_float_info to
    dump the float pointer registers.  It can be reused by backend to
    print something more than float point registers.
 2. we want to simply the caller of print_float_info,
    infcmd.c:print_float_info.

gdb:

2014-12-17  Yao Qi  <yao@codesourcery.com>

 	* gdbarch.sh (print_float_info): Change its type from 'M' to 'm'.
	* gdbarch.c: Re-generated.
	* gdbarch.h: Likewise.
	* infcmd.c (default_print_float_info): New function.
	(print_float_info): Move code to default_print_float_info and
	call it.
	* inferior.h (default_print_float_info): Declare it.
---
 gdb/gdbarch.c  | 13 ++-----------
 gdb/gdbarch.h  |  2 --
 gdb/gdbarch.sh |  2 +-
 gdb/infcmd.c   | 45 ++++++++++++++++++++++++---------------------
 gdb/inferior.h |  5 +++++
 5 files changed, 32 insertions(+), 35 deletions(-)

diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 657708e..93110af 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -379,6 +379,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
   gdbarch->deprecated_fp_regnum = -1;
   gdbarch->call_dummy_location = AT_ENTRY_POINT;
   gdbarch->print_registers_info = default_print_registers_info;
+  gdbarch->print_float_info = default_print_float_info;
   gdbarch->register_sim_regno = legacy_register_sim_regno;
   gdbarch->cannot_fetch_register = cannot_register_not;
   gdbarch->cannot_store_register = cannot_register_not;
@@ -531,7 +532,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of call_dummy_location, invalid_p == 0 */
   /* Skip verify of push_dummy_code, has predicate.  */
   /* Skip verify of print_registers_info, invalid_p == 0 */
-  /* Skip verify of print_float_info, has predicate.  */
+  /* Skip verify of print_float_info, invalid_p == 0 */
   /* Skip verify of print_vector_info, has predicate.  */
   /* Skip verify of register_sim_regno, invalid_p == 0 */
   /* Skip verify of cannot_fetch_register, invalid_p == 0 */
@@ -1089,9 +1090,6 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: pointer_to_address = <%s>\n",
                       host_address_to_string (gdbarch->pointer_to_address));
   fprintf_unfiltered (file,
-                      "gdbarch_dump: gdbarch_print_float_info_p() = %d\n",
-                      gdbarch_print_float_info_p (gdbarch));
-  fprintf_unfiltered (file,
                       "gdbarch_dump: print_float_info = <%s>\n",
                       host_address_to_string (gdbarch->print_float_info));
   fprintf_unfiltered (file,
@@ -2235,13 +2233,6 @@ set_gdbarch_print_registers_info (struct gdbarch *gdbarch,
   gdbarch->print_registers_info = print_registers_info;
 }
 
-int
-gdbarch_print_float_info_p (struct gdbarch *gdbarch)
-{
-  gdb_assert (gdbarch != NULL);
-  return gdbarch->print_float_info != NULL;
-}
-
 void
 gdbarch_print_float_info (struct gdbarch *gdbarch, struct ui_file *file, struct frame_info *frame, const char *args)
 {
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index a40863d..c22fc7d 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -377,8 +377,6 @@ typedef void (gdbarch_print_registers_info_ftype) (struct gdbarch *gdbarch, stru
 extern void gdbarch_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file, struct frame_info *frame, int regnum, int all);
 extern void set_gdbarch_print_registers_info (struct gdbarch *gdbarch, gdbarch_print_registers_info_ftype *print_registers_info);
 
-extern int gdbarch_print_float_info_p (struct gdbarch *gdbarch);
-
 typedef void (gdbarch_print_float_info_ftype) (struct gdbarch *gdbarch, struct ui_file *file, struct frame_info *frame, const char *args);
 extern void gdbarch_print_float_info (struct gdbarch *gdbarch, struct ui_file *file, struct frame_info *frame, const char *args);
 extern void set_gdbarch_print_float_info (struct gdbarch *gdbarch, gdbarch_print_float_info_ftype *print_float_info);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index a643d00..685f08f 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -479,7 +479,7 @@ v:int:call_dummy_location::::AT_ENTRY_POINT::0
 M:CORE_ADDR:push_dummy_code:CORE_ADDR sp, CORE_ADDR funaddr, struct value **args, int nargs, struct type *value_type, CORE_ADDR *real_pc, CORE_ADDR *bp_addr, struct regcache *regcache:sp, funaddr, args, nargs, value_type, real_pc, bp_addr, regcache
 
 m:void:print_registers_info:struct ui_file *file, struct frame_info *frame, int regnum, int all:file, frame, regnum, all::default_print_registers_info::0
-M:void:print_float_info:struct ui_file *file, struct frame_info *frame, const char *args:file, frame, args
+m:void:print_float_info:struct ui_file *file, struct frame_info *frame, const char *args:file, frame, args::default_print_float_info::0
 M:void:print_vector_info:struct ui_file *file, struct frame_info *frame, const char *args:file, frame, args
 # MAP a GDB RAW register number onto a simulator register number.  See
 # also include/...-sim.h.
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index de0d24d..e51cb7b 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -2864,34 +2864,37 @@ interrupt_command (char *args, int from_tty)
     }
 }
 
+void
+default_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
+			  struct frame_info *frame, const char *args)
+{
+  int regnum;
+  int printed_something = 0;
+
+  for (regnum = 0;
+       regnum < gdbarch_num_regs (gdbarch)
+	 + gdbarch_num_pseudo_regs (gdbarch);
+       regnum++)
+    {
+      if (gdbarch_register_reggroup_p (gdbarch, regnum, float_reggroup))
+	{
+	  printed_something = 1;
+	  gdbarch_print_registers_info (gdbarch, file, frame, regnum, 1);
+	}
+    }
+  if (!printed_something)
+    fprintf_filtered (file, "No floating-point info "
+		      "available for this processor.\n");
+}
+
 static void
 print_float_info (struct ui_file *file,
 		  struct frame_info *frame, const char *args)
 {
   struct gdbarch *gdbarch = get_frame_arch (frame);
 
-  if (gdbarch_print_float_info_p (gdbarch))
-    gdbarch_print_float_info (gdbarch, file, frame, args);
-  else
-    {
-      int regnum;
-      int printed_something = 0;
+  gdbarch_print_float_info (gdbarch, file, frame, args);
 
-      for (regnum = 0;
-	   regnum < gdbarch_num_regs (gdbarch)
-		    + gdbarch_num_pseudo_regs (gdbarch);
-	   regnum++)
-	{
-	  if (gdbarch_register_reggroup_p (gdbarch, regnum, float_reggroup))
-	    {
-	      printed_something = 1;
-	      gdbarch_print_registers_info (gdbarch, file, frame, regnum, 1);
-	    }
-	}
-      if (!printed_something)
-	fprintf_filtered (file, "No floating-point info "
-			  "available for this processor.\n");
-    }
 }
 
 static void
diff --git a/gdb/inferior.h b/gdb/inferior.h
index eebc034..e10197a 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -106,6 +106,11 @@ extern void default_print_registers_info (struct gdbarch *gdbarch,
 					  struct frame_info *frame,
 					  int regnum, int all);
 
+extern void default_print_float_info (struct gdbarch *gdbarch,
+				      struct ui_file *file,
+				      struct frame_info *frame,
+				      const char *args);
+
 extern void child_terminal_info (struct target_ops *self, const char *, int);
 
 extern void term_info (char *, int);
-- 
1.9.3

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 1/3] Remove h8300_print_float_info
  2014-12-17  6:46 [PATCH 0/3, V2] MIPS: Provide FPU info and decode FCSR in `info float' Yao Qi
@ 2014-12-17  6:46 ` Yao Qi
  2014-12-17  6:46 ` [PATCH 3/3] MIPS: Provide FPU info and decode FCSR in `info float' Yao Qi
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 13+ messages in thread
From: Yao Qi @ 2014-12-17  6:46 UTC (permalink / raw)
  To: gdb-patches

In infcmd.c:print_float_info, if the architecture doesn't have gdbarch
method print_float_info implemented and doesn't float reggroup, GDB
will prints "No floating-point info available for this processor."
The h8300 port doesn't have float registers, and don't need to
implement print_float_info.  This patch is to remove it.

gdb:

2014-12-17  Yao Qi  <yao@codesourcery.com>

	* h8300-tdep.c (h8300_print_float_info): Remove.
	(h8300_gdbarch_init): Remove the call to
	set_gdbarch_print_float_info.
---
 gdb/h8300-tdep.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/gdb/h8300-tdep.c b/gdb/h8300-tdep.c
index 0f58553..cd2b344 100644
--- a/gdb/h8300-tdep.c
+++ b/gdb/h8300-tdep.c
@@ -1256,14 +1256,6 @@ h8300_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
   return breakpoint;
 }
 
-static void
-h8300_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
-			struct frame_info *frame, const char *args)
-{
-  fprintf_filtered (file, "\
-No floating-point info available for this processor.\n");
-}
-
 static struct gdbarch *
 h8300_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 {
@@ -1375,7 +1367,6 @@ h8300_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_pc_regnum (gdbarch, E_PC_REGNUM);
   set_gdbarch_register_type (gdbarch, h8300_register_type);
   set_gdbarch_print_registers_info (gdbarch, h8300_print_registers_info);
-  set_gdbarch_print_float_info (gdbarch, h8300_print_float_info);
 
   /*
    * Frame Info
-- 
1.9.3

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 0/3, V2] MIPS: Provide FPU info and decode FCSR in `info float'
@ 2014-12-17  6:46 Yao Qi
  2014-12-17  6:46 ` [PATCH 1/3] Remove h8300_print_float_info Yao Qi
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Yao Qi @ 2014-12-17  6:46 UTC (permalink / raw)
  To: gdb-patches

This patch series is the V2, to mainly address review comments in V1,
which can be found in https://sourceware.org/ml/gdb-patches/2012-05/msg00938.html

In the review to V1, Joel suggested to continue dumping float point
registers in 'info float' and we do that in V2 by calling
print_float_info's default implementation default_print_float_info.

During writing this patch, I find h8300_print_float_info isn't needed.
I remove it too.

This patch series is tested under mips-linux-gnu.  Is it OK?

*** BLURB HERE ***

Yao Qi (3):
  Remove h8300_print_float_info
  Refactor gdbarch method print_float_info
  MIPS: Provide FPU info and decode FCSR in `info float'

 gdb/gdbarch.c                    | 13 +-----
 gdb/gdbarch.h                    |  2 -
 gdb/gdbarch.sh                   |  2 +-
 gdb/h8300-tdep.c                 |  9 ----
 gdb/infcmd.c                     | 45 ++++++++++---------
 gdb/inferior.h                   |  5 +++
 gdb/mips-tdep.c                  | 95 ++++++++++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/float.exp |  9 +++-
 8 files changed, 135 insertions(+), 45 deletions(-)

-- 
1.9.3

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/3] MIPS: Provide FPU info and decode FCSR in `info float'
  2014-12-17  6:46 ` [PATCH 3/3] MIPS: Provide FPU info and decode FCSR in `info float' Yao Qi
@ 2014-12-17 10:53   ` Pedro Alves
  2014-12-17 12:40     ` Yao Qi
  2014-12-21  0:14     ` Maciej W. Rozycki
  0 siblings, 2 replies; 13+ messages in thread
From: Pedro Alves @ 2014-12-17 10:53 UTC (permalink / raw)
  To: Yao Qi, gdb-patches

On 12/17/2014 06:46 AM, Yao Qi wrote:

> +static void
> +mips_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
> +		      struct frame_info *frame, const char *args)
> +{
> +  int fcsr = mips_regnum (gdbarch)->fp_control_status;
> +  enum mips_fpu_type type = MIPS_FPU_TYPE (gdbarch);
> +  ULONGEST fcs = 0;
> +  int i;
> +
> +  if (fcsr == -1 || !deprecated_frame_register_read (frame, fcsr, NULL))
> +    type = MIPS_FPU_NONE;

"deprecated" method usage alert.  It's better to use methods that return
values and then print "<unsaved>", "<unavailable>" as appropriate,
though in this case you may be able to just use read_frame_register_unsigned
instead.

> +
> +  fprintf_filtered (file, "fpu type: %s\n",
> +		    type == MIPS_FPU_DOUBLE ? "double-precision"
> +		    : type == MIPS_FPU_SINGLE ? "single-precision"
> +		    : "none / unused");
> +
> +  if (type == MIPS_FPU_NONE)
> +    return;
> +

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/3] MIPS: Provide FPU info and decode FCSR in `info float'
  2014-12-17 10:53   ` Pedro Alves
@ 2014-12-17 12:40     ` Yao Qi
  2014-12-18  1:07       ` Yao Qi
  2014-12-21  0:14     ` Maciej W. Rozycki
  1 sibling, 1 reply; 13+ messages in thread
From: Yao Qi @ 2014-12-17 12:40 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves <palves@redhat.com> writes:

> "deprecated" method usage alert.  It's better to use methods that return
> values and then print "<unsaved>", "<unavailable>" as appropriate,
> though in this case you may be able to just use
> read_frame_register_unsigned
> instead.

OK, I replace it with read_frame_register_unsigned in the updated
patch below.

-- 
Yao (齐尧)

---
 gdb/mips-tdep.c                  | 93 ++++++++++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/float.exp |  9 +++-
 2 files changed, 101 insertions(+), 1 deletion(-)

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index eb99910..60f43ac 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -73,6 +73,9 @@ static int micromips_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
 static int mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
 					     CORE_ADDR addr, int mustbe32);
 
+static void mips_print_float_info (struct gdbarch *, struct ui_file *,
+				   struct frame_info *, const char *);
+
 /* 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)
@@ -6387,6 +6390,94 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
 			      &opts, 0, file);
 }
 
+/* Print IEEE exception condition bits in FLAGS.  */
+
+static void
+print_fpu_flags (struct ui_file *file, int flags)
+{
+  if (flags & (1 << 0))
+    fputs_filtered (" inexact", file);
+  if (flags & (1 << 1))
+    fputs_filtered (" uflow", file);
+  if (flags & (1 << 2))
+    fputs_filtered (" oflow", file);
+  if (flags & (1 << 3))
+    fputs_filtered (" div0", file);
+  if (flags & (1 << 4))
+    fputs_filtered (" inval", file);
+  if (flags & (1 << 5))
+    fputs_filtered (" unimp", file);
+  fputc_filtered ('\n', file);
+}
+
+/* Print interesting information about the floating point processor
+   (if present) or emulator.  */
+
+static void
+mips_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
+		      struct frame_info *frame, const char *args)
+{
+  int fcsr = mips_regnum (gdbarch)->fp_control_status;
+  enum mips_fpu_type type = MIPS_FPU_TYPE (gdbarch);
+  ULONGEST fcs = 0;
+  int i;
+
+  if (fcsr == -1 || !read_frame_register_unsigned (frame, fcsr, &fcs))
+    type = MIPS_FPU_NONE;
+
+  fprintf_filtered (file, "fpu type: %s\n",
+		    type == MIPS_FPU_DOUBLE ? "double-precision"
+		    : type == MIPS_FPU_SINGLE ? "single-precision"
+		    : "none / unused");
+
+  if (type == MIPS_FPU_NONE)
+    return;
+
+  fprintf_filtered (file, "reg size: %d bits\n",
+		    register_size (gdbarch, mips_regnum (gdbarch)->fp0) * 8);
+
+  fputs_filtered ("cond    :", file);
+  if (fcs & (1 << 23))
+    fputs_filtered (" 0", file);
+  for (i = 1; i <= 7; i++)
+    if (fcs & (1 << (24 + i)))
+      fprintf_filtered (file, " %d", i);
+  fputc_filtered ('\n', file);
+
+  fputs_filtered ("cause   :", file);
+  print_fpu_flags (file, (fcs >> 12) & 0x3f);
+  fputs ("mask    :", stdout);
+  print_fpu_flags (file, (fcs >> 7) & 0x1f);
+  fputs ("flags   :", stdout);
+  print_fpu_flags (file, (fcs >> 2) & 0x1f);
+
+  fputs_filtered ("rounding: ", file);
+  switch (fcs & 3)
+    {
+    case 0: fputs_filtered ("nearest\n", file); break;
+    case 1: fputs_filtered ("zero\n", file); break;
+    case 2: fputs_filtered ("+inf\n", file); break;
+    case 3: fputs_filtered ("-inf\n", file); break;
+    }
+
+  fputs_filtered ("flush   :", file);
+  if (fcs & (1 << 21))
+    fputs_filtered (" nearest", file);
+  if (fcs & (1 << 22))
+    fputs_filtered (" override", file);
+  if (fcs & (1 << 24))
+    fputs_filtered (" zero", file);
+  if ((fcs & (0xb << 21)) == 0)
+    fputs_filtered (" no", file);
+  fputc_filtered ('\n', file);
+
+  fprintf_filtered (file, "nan2008 : %s\n", fcs & (1 << 18) ? "yes" : "no");
+  fprintf_filtered (file, "abs2008 : %s\n", fcs & (1 << 19) ? "yes" : "no");
+  fputc_filtered ('\n', file);
+
+  default_print_float_info (gdbarch, file, frame, args);
+}
+
 /* Replacement for generic do_registers_info.
    Print regs in pretty columns.  */
 
@@ -8737,6 +8828,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_push_dummy_code (gdbarch, mips_push_dummy_code);
   set_gdbarch_frame_align (gdbarch, mips_frame_align);
 
+  set_gdbarch_print_float_info (gdbarch, mips_print_float_info);
+
   set_gdbarch_convert_register_p (gdbarch, mips_convert_register_p);
   set_gdbarch_register_to_value (gdbarch, mips_register_to_value);
   set_gdbarch_value_to_register (gdbarch, mips_value_to_register);
diff --git a/gdb/testsuite/gdb.base/float.exp b/gdb/testsuite/gdb.base/float.exp
index 5da9630..3ecb01b 100644
--- a/gdb/testsuite/gdb.base/float.exp
+++ b/gdb/testsuite/gdb.base/float.exp
@@ -68,7 +68,14 @@ if { [istarget "aarch64*-*-*"] } then {
 	}
     }
 } elseif [istarget "mips*-*-*"] then {
-    gdb_test "info float" "f0:.*flt:.*dbl:.*" "info float"
+    gdb_test_multiple "info float" "info float" {
+	-re "fpu type: none*" {
+	      pass "info float (without FPU)"
+	  }
+	-re "fpu type:.*cause.*mask.*flags.*round.*flush.*" {
+	      pass "info float (with FPU)"
+	  }
+    }
 } elseif [istarget "powerpc*-*-*"] then {
     gdb_test_multiple "info float" "info_float" {
         -re "f0.*f1.*f31.*fpscr.*$gdb_prompt $" {
-- 
1.9.3

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/3] Refactor gdbarch method print_float_info
  2014-12-17  6:46 ` [PATCH 2/3] Refactor gdbarch method print_float_info Yao Qi
@ 2014-12-17 13:24   ` Pedro Alves
  2014-12-18  1:02     ` Yao Qi
  0 siblings, 1 reply; 13+ messages in thread
From: Pedro Alves @ 2014-12-17 13:24 UTC (permalink / raw)
  To: Yao Qi, gdb-patches

Thanks!  I took another look and I have a few
further comments.  Sorry I didn't send them the first
time around.

On 12/17/2014 06:46 AM, Yao Qi wrote:

>  2. we want to simply the caller of print_float_info,

"simplify"


> +void
> +default_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
> +			  struct frame_info *frame, const char *args)

Could you add an "See inferior.h." comment?

> +{
> +  int regnum;
> +  int printed_something = 0;
> +
> +  for (regnum = 0;
> +       regnum < gdbarch_num_regs (gdbarch)
> +	 + gdbarch_num_pseudo_regs (gdbarch);
> +       regnum++)
> +    {
> +      if (gdbarch_register_reggroup_p (gdbarch, regnum, float_reggroup))
> +	{
> +	  printed_something = 1;
> +	  gdbarch_print_registers_info (gdbarch, file, frame, regnum, 1);
> +	}
> +    }
> +  if (!printed_something)
> +    fprintf_filtered (file, "No floating-point info "
> +		      "available for this processor.\n");
> +}
> +
>  static void
>  print_float_info (struct ui_file *file,
>  		  struct frame_info *frame, const char *args)
>  {
>    struct gdbarch *gdbarch = get_frame_arch (frame);
>  
> -  if (gdbarch_print_float_info_p (gdbarch))
> -    gdbarch_print_float_info (gdbarch, file, frame, args);
> -  else
> -    {
> -      int regnum;
> -      int printed_something = 0;
> +  gdbarch_print_float_info (gdbarch, file, frame, args);

I think there's only one caller of print_float_info,
so we could inline this there and eliminate print_float_info.

> index eebc034..e10197a 100644
> --- a/gdb/inferior.h
> +++ b/gdb/inferior.h
> @@ -106,6 +106,11 @@ extern void default_print_registers_info (struct gdbarch *gdbarch,
>  					  struct frame_info *frame,
>  					  int regnum, int all);
>  
> +extern void default_print_float_info (struct gdbarch *gdbarch,
> +				      struct ui_file *file,
> +				      struct frame_info *frame,
> +				      const char *args);
> +

Could you add an intro comment?  Something like:

/* Default implementation of gdbarch_print_float_info.  Prints
   the values of all floating point registers.  */

>  extern void child_terminal_info (struct target_ops *self, const char *, int);
>  
>  extern void term_info (char *, int);
> 


>  } elseif [istarget "mips*-*-*"] then {
> -    gdb_test "info float" "f0:.*flt:.*dbl:.*" "info float"
> +    gdb_test_multiple "info float" "info float" {
> +	-re "fpu type: none*" {
> +	      pass "info float (without FPU)"
> +	  }
> +	-re "fpu type:.*cause.*mask.*flags.*round.*flush.*" {
> +	      pass "info float (with FPU)"
> +	  }

Missing "$gdb_prompt $" at the end of those regexs.

Also, with v2 we still print the register values.
So ISTM that it'd be good if the "f0:.*flt:.*dbl:.*" regex is
still part of the expected output?  And if in the none case
we _shouldn't see those, then the test could make sure
that's how things work?

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/3] Refactor gdbarch method print_float_info
  2014-12-17 13:24   ` Pedro Alves
@ 2014-12-18  1:02     ` Yao Qi
  2014-12-18 11:14       ` Pedro Alves
  0 siblings, 1 reply; 13+ messages in thread
From: Yao Qi @ 2014-12-18  1:02 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Pedro Alves <palves@redhat.com> writes:

> Thanks!  I took another look and I have a few
> further comments.  Sorry I didn't send them the first
> time around.

Thanks for the review.  Patch below is updated to address all your comments.

>>  } elseif [istarget "mips*-*-*"] then {
>> -    gdb_test "info float" "f0:.*flt:.*dbl:.*" "info float"
>> +    gdb_test_multiple "info float" "info float" {
>> +	-re "fpu type: none*" {
>> +	      pass "info float (without FPU)"
>> +	  }
>> +	-re "fpu type:.*cause.*mask.*flags.*round.*flush.*" {
>> +	      pass "info float (with FPU)"
>> +	  }
>
> Missing "$gdb_prompt $" at the end of those regexs.
>
> Also, with v2 we still print the register values.
> So ISTM that it'd be good if the "f0:.*flt:.*dbl:.*" regex is
> still part of the expected output?  And if in the none case
> we _shouldn't see those, then the test could make sure
> that's how things work?

I am OK to restrict the pattern.  I'll update patch 3/3.

-- 
Yao (齐尧)

Subject: [PATCH] Refactor gdbarch method print_float_info

This patch is to change print_float_info gdbarch method for the
following two reasons,

 1. we want to add a default implementation of print_float_info to
    dump the float pointer registers.  It can be reused by backend to
    print something more than float point registers.
 2. we want to simplify the caller of print_float_info,
    infcmd.c:print_float_info.

gdb:

2014-12-18  Yao Qi  <yao@codesourcery.com>

 	* gdbarch.sh (print_float_info): Change its type from 'M' to 'm'.
	* gdbarch.c: Re-generated.
	* gdbarch.h: Likewise.
	* infcmd.c (default_print_float_info): New function.
	(print_float_info): Removed.  Move code to
	default_print_float_info.
	(float_info): Adjust to call gdbarch_print_float_info.
	* inferior.h (default_print_float_info): Declare it.

diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 657708e..93110af 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -379,6 +379,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
   gdbarch->deprecated_fp_regnum = -1;
   gdbarch->call_dummy_location = AT_ENTRY_POINT;
   gdbarch->print_registers_info = default_print_registers_info;
+  gdbarch->print_float_info = default_print_float_info;
   gdbarch->register_sim_regno = legacy_register_sim_regno;
   gdbarch->cannot_fetch_register = cannot_register_not;
   gdbarch->cannot_store_register = cannot_register_not;
@@ -531,7 +532,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of call_dummy_location, invalid_p == 0 */
   /* Skip verify of push_dummy_code, has predicate.  */
   /* Skip verify of print_registers_info, invalid_p == 0 */
-  /* Skip verify of print_float_info, has predicate.  */
+  /* Skip verify of print_float_info, invalid_p == 0 */
   /* Skip verify of print_vector_info, has predicate.  */
   /* Skip verify of register_sim_regno, invalid_p == 0 */
   /* Skip verify of cannot_fetch_register, invalid_p == 0 */
@@ -1089,9 +1090,6 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: pointer_to_address = <%s>\n",
                       host_address_to_string (gdbarch->pointer_to_address));
   fprintf_unfiltered (file,
-                      "gdbarch_dump: gdbarch_print_float_info_p() = %d\n",
-                      gdbarch_print_float_info_p (gdbarch));
-  fprintf_unfiltered (file,
                       "gdbarch_dump: print_float_info = <%s>\n",
                       host_address_to_string (gdbarch->print_float_info));
   fprintf_unfiltered (file,
@@ -2235,13 +2233,6 @@ set_gdbarch_print_registers_info (struct gdbarch *gdbarch,
   gdbarch->print_registers_info = print_registers_info;
 }
 
-int
-gdbarch_print_float_info_p (struct gdbarch *gdbarch)
-{
-  gdb_assert (gdbarch != NULL);
-  return gdbarch->print_float_info != NULL;
-}
-
 void
 gdbarch_print_float_info (struct gdbarch *gdbarch, struct ui_file *file, struct frame_info *frame, const char *args)
 {
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index a40863d..c22fc7d 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -377,8 +377,6 @@ typedef void (gdbarch_print_registers_info_ftype) (struct gdbarch *gdbarch, stru
 extern void gdbarch_print_registers_info (struct gdbarch *gdbarch, struct ui_file *file, struct frame_info *frame, int regnum, int all);
 extern void set_gdbarch_print_registers_info (struct gdbarch *gdbarch, gdbarch_print_registers_info_ftype *print_registers_info);
 
-extern int gdbarch_print_float_info_p (struct gdbarch *gdbarch);
-
 typedef void (gdbarch_print_float_info_ftype) (struct gdbarch *gdbarch, struct ui_file *file, struct frame_info *frame, const char *args);
 extern void gdbarch_print_float_info (struct gdbarch *gdbarch, struct ui_file *file, struct frame_info *frame, const char *args);
 extern void set_gdbarch_print_float_info (struct gdbarch *gdbarch, gdbarch_print_float_info_ftype *print_float_info);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index a643d00..685f08f 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -479,7 +479,7 @@ v:int:call_dummy_location::::AT_ENTRY_POINT::0
 M:CORE_ADDR:push_dummy_code:CORE_ADDR sp, CORE_ADDR funaddr, struct value **args, int nargs, struct type *value_type, CORE_ADDR *real_pc, CORE_ADDR *bp_addr, struct regcache *regcache:sp, funaddr, args, nargs, value_type, real_pc, bp_addr, regcache
 
 m:void:print_registers_info:struct ui_file *file, struct frame_info *frame, int regnum, int all:file, frame, regnum, all::default_print_registers_info::0
-M:void:print_float_info:struct ui_file *file, struct frame_info *frame, const char *args:file, frame, args
+m:void:print_float_info:struct ui_file *file, struct frame_info *frame, const char *args:file, frame, args::default_print_float_info::0
 M:void:print_vector_info:struct ui_file *file, struct frame_info *frame, const char *args:file, frame, args
 # MAP a GDB RAW register number onto a simulator register number.  See
 # also include/...-sim.h.
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index de0d24d..58e4d1f 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -2864,43 +2864,41 @@ interrupt_command (char *args, int from_tty)
     }
 }
 
-static void
-print_float_info (struct ui_file *file,
-		  struct frame_info *frame, const char *args)
+/* See inferior.h.  */
+
+void
+default_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
+			  struct frame_info *frame, const char *args)
 {
-  struct gdbarch *gdbarch = get_frame_arch (frame);
+  int regnum;
+  int printed_something = 0;
 
-  if (gdbarch_print_float_info_p (gdbarch))
-    gdbarch_print_float_info (gdbarch, file, frame, args);
-  else
+  for (regnum = 0;
+       regnum < gdbarch_num_regs (gdbarch)
+	 + gdbarch_num_pseudo_regs (gdbarch);
+       regnum++)
     {
-      int regnum;
-      int printed_something = 0;
-
-      for (regnum = 0;
-	   regnum < gdbarch_num_regs (gdbarch)
-		    + gdbarch_num_pseudo_regs (gdbarch);
-	   regnum++)
+      if (gdbarch_register_reggroup_p (gdbarch, regnum, float_reggroup))
 	{
-	  if (gdbarch_register_reggroup_p (gdbarch, regnum, float_reggroup))
-	    {
-	      printed_something = 1;
-	      gdbarch_print_registers_info (gdbarch, file, frame, regnum, 1);
-	    }
+	  printed_something = 1;
+	  gdbarch_print_registers_info (gdbarch, file, frame, regnum, 1);
 	}
-      if (!printed_something)
-	fprintf_filtered (file, "No floating-point info "
-			  "available for this processor.\n");
     }
+  if (!printed_something)
+    fprintf_filtered (file, "No floating-point info "
+		      "available for this processor.\n");
 }
 
 static void
 float_info (char *args, int from_tty)
 {
+  struct frame_info *frame;
+
   if (!target_has_registers)
     error (_("The program has no registers now."));
 
-  print_float_info (gdb_stdout, get_selected_frame (NULL), args);
+  frame = get_selected_frame (NULL);
+  gdbarch_print_float_info (get_frame_arch (frame), gdb_stdout, frame, args);
 }
 \f
 static void
diff --git a/gdb/inferior.h b/gdb/inferior.h
index eebc034..b607fbf 100644
--- a/gdb/inferior.h
+++ b/gdb/inferior.h
@@ -106,6 +106,14 @@ extern void default_print_registers_info (struct gdbarch *gdbarch,
 					  struct frame_info *frame,
 					  int regnum, int all);
 
+/* Default implementation of gdbarch_print_float_info.  Print
+   the values of all floating point registers.  */
+
+extern void default_print_float_info (struct gdbarch *gdbarch,
+				      struct ui_file *file,
+				      struct frame_info *frame,
+				      const char *args);
+
 extern void child_terminal_info (struct target_ops *self, const char *, int);
 
 extern void term_info (char *, int);

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/3] MIPS: Provide FPU info and decode FCSR in `info float'
  2014-12-17 12:40     ` Yao Qi
@ 2014-12-18  1:07       ` Yao Qi
  2014-12-18 11:16         ` Pedro Alves
  0 siblings, 1 reply; 13+ messages in thread
From: Yao Qi @ 2014-12-18  1:07 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches

Yao Qi <yao@codesourcery.com> writes:

>  } elseif [istarget "mips*-*-*"] then {
> -    gdb_test "info float" "f0:.*flt:.*dbl:.*" "info float"
> +    gdb_test_multiple "info float" "info float" {
> +	-re "fpu type: none*" {
> +	      pass "info float (without FPU)"
> +	  }
> +	-re "fpu type:.*cause.*mask.*flags.*round.*flush.*" {
> +	      pass "info float (with FPU)"
> +	  }
> +    }

The updated patch adds the "$gdb_prompt $" at the end of those patterns
and restrict the restrict the patterns.

-- 
Yao (齐尧)

Subject: [PATCH] MIPS: Provide FPU info and decode FCSR in `info float'

This patch is the V2.  V1 can be found in
https://sourceware.org/ml/gdb-patches/2012-05/msg00938.html
V2 is to address Joel's comment
<https://sourceware.org/ml/gdb-patches/2012-06/msg00289.html> about
keeping dumping floating point registers.  Additionally, command
'info float' prints bits on nan2008 and abs2008.

------------------------------------------------------------------

 The change below provides a MIPS-specific handler for the:

(gdb) info float

command.  It provides information about the FPU type available (if any),
the FPU register width, and decodes the CP1 Floating Point Control and
Status Register (FCSR):

(gdb) print /x $fsr
$1 = 0xff83ffff
(gdb) info float
fpu type: double-precision
reg size: 32 bits
cond    : 0 1 2 3 4 5 6 7
cause   : inexact uflow oflow div0 inval unimp
mask    : inexact uflow oflow div0 inval
flags   : inexact uflow oflow div0 inval
rounding: -inf
flush   : zero

 One point to note about CP1.FCSR are the non-standard Flush-to-Nearest
and Flush-Override bits.  They are not a part of the MIPS architecture and
take two positions reserved for an implementation-dependent use in the
architecture.  They are present in all the FPU implementations made by
MIPS Technologies since the spin-off from SGI.

 I haven't been able to track down a single other MIPS FPU implementation
that would make any use of these bits and they are required to be
hardwired to zero by the architecture specification if unimplemented.
Therefore I think it makes sense to report them in the current way.

 GDB has no guaranteed access to the CP0 Processor Identification (PRId)
register to validate this feature properly and the ID information stored
in the CP1 Floating Point Implementation Register (FIR) is from my
experience not reliable enough (there's no Company ID available there for
once unlike in CP0.PRId and Processor ID is not guaranteed to be unique).

 As a side note we should probably dump CP1.FIR information as well, as
there's useful stuff indicating some FPU features there.  That's material
for another change however.

gdb/

2014-12-17  Nigel Stephens  <nigel@mips.com>
            Maciej W. Rozycki  <macro@codesourcery.com>

	* mips-tdep.c (print_fpu_flags): New function.
	(mips_print_float_info): Likewise.
	(mips_gdbarch_init): Install mips_print_float_info as gdbarch
	print_float_info routine.

gdb/testsuite/

2014-12-17  Nigel Stephens  <nigel@mips.com>
            Maciej W. Rozycki  <macro@codesourcery.com>

	* gdb.base/float.exp: Handle the new output from "info float" on
	MIPS targets.

diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c
index eb99910..60f43ac 100644
--- a/gdb/mips-tdep.c
+++ b/gdb/mips-tdep.c
@@ -73,6 +73,9 @@ static int micromips_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
 static int mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch,
 					     CORE_ADDR addr, int mustbe32);
 
+static void mips_print_float_info (struct gdbarch *, struct ui_file *,
+				   struct frame_info *, const char *);
+
 /* 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)
@@ -6387,6 +6390,94 @@ mips_print_register (struct ui_file *file, struct frame_info *frame,
 			      &opts, 0, file);
 }
 
+/* Print IEEE exception condition bits in FLAGS.  */
+
+static void
+print_fpu_flags (struct ui_file *file, int flags)
+{
+  if (flags & (1 << 0))
+    fputs_filtered (" inexact", file);
+  if (flags & (1 << 1))
+    fputs_filtered (" uflow", file);
+  if (flags & (1 << 2))
+    fputs_filtered (" oflow", file);
+  if (flags & (1 << 3))
+    fputs_filtered (" div0", file);
+  if (flags & (1 << 4))
+    fputs_filtered (" inval", file);
+  if (flags & (1 << 5))
+    fputs_filtered (" unimp", file);
+  fputc_filtered ('\n', file);
+}
+
+/* Print interesting information about the floating point processor
+   (if present) or emulator.  */
+
+static void
+mips_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
+		      struct frame_info *frame, const char *args)
+{
+  int fcsr = mips_regnum (gdbarch)->fp_control_status;
+  enum mips_fpu_type type = MIPS_FPU_TYPE (gdbarch);
+  ULONGEST fcs = 0;
+  int i;
+
+  if (fcsr == -1 || !read_frame_register_unsigned (frame, fcsr, &fcs))
+    type = MIPS_FPU_NONE;
+
+  fprintf_filtered (file, "fpu type: %s\n",
+		    type == MIPS_FPU_DOUBLE ? "double-precision"
+		    : type == MIPS_FPU_SINGLE ? "single-precision"
+		    : "none / unused");
+
+  if (type == MIPS_FPU_NONE)
+    return;
+
+  fprintf_filtered (file, "reg size: %d bits\n",
+		    register_size (gdbarch, mips_regnum (gdbarch)->fp0) * 8);
+
+  fputs_filtered ("cond    :", file);
+  if (fcs & (1 << 23))
+    fputs_filtered (" 0", file);
+  for (i = 1; i <= 7; i++)
+    if (fcs & (1 << (24 + i)))
+      fprintf_filtered (file, " %d", i);
+  fputc_filtered ('\n', file);
+
+  fputs_filtered ("cause   :", file);
+  print_fpu_flags (file, (fcs >> 12) & 0x3f);
+  fputs ("mask    :", stdout);
+  print_fpu_flags (file, (fcs >> 7) & 0x1f);
+  fputs ("flags   :", stdout);
+  print_fpu_flags (file, (fcs >> 2) & 0x1f);
+
+  fputs_filtered ("rounding: ", file);
+  switch (fcs & 3)
+    {
+    case 0: fputs_filtered ("nearest\n", file); break;
+    case 1: fputs_filtered ("zero\n", file); break;
+    case 2: fputs_filtered ("+inf\n", file); break;
+    case 3: fputs_filtered ("-inf\n", file); break;
+    }
+
+  fputs_filtered ("flush   :", file);
+  if (fcs & (1 << 21))
+    fputs_filtered (" nearest", file);
+  if (fcs & (1 << 22))
+    fputs_filtered (" override", file);
+  if (fcs & (1 << 24))
+    fputs_filtered (" zero", file);
+  if ((fcs & (0xb << 21)) == 0)
+    fputs_filtered (" no", file);
+  fputc_filtered ('\n', file);
+
+  fprintf_filtered (file, "nan2008 : %s\n", fcs & (1 << 18) ? "yes" : "no");
+  fprintf_filtered (file, "abs2008 : %s\n", fcs & (1 << 19) ? "yes" : "no");
+  fputc_filtered ('\n', file);
+
+  default_print_float_info (gdbarch, file, frame, args);
+}
+
 /* Replacement for generic do_registers_info.
    Print regs in pretty columns.  */
 
@@ -8737,6 +8828,8 @@ mips_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_push_dummy_code (gdbarch, mips_push_dummy_code);
   set_gdbarch_frame_align (gdbarch, mips_frame_align);
 
+  set_gdbarch_print_float_info (gdbarch, mips_print_float_info);
+
   set_gdbarch_convert_register_p (gdbarch, mips_convert_register_p);
   set_gdbarch_register_to_value (gdbarch, mips_register_to_value);
   set_gdbarch_value_to_register (gdbarch, mips_value_to_register);
diff --git a/gdb/testsuite/gdb.base/float.exp b/gdb/testsuite/gdb.base/float.exp
index 5da9630..fbbd682 100644
--- a/gdb/testsuite/gdb.base/float.exp
+++ b/gdb/testsuite/gdb.base/float.exp
@@ -68,7 +68,14 @@ if { [istarget "aarch64*-*-*"] } then {
 	}
     }
 } elseif [istarget "mips*-*-*"] then {
-    gdb_test "info float" "f0:.*flt:.*dbl:.*" "info float"
+    gdb_test_multiple "info float" "info float" {
+	-re "fpu type: none / unused\r\n$gdb_prompt $" {
+	      pass "info float (without FPU)"
+	  }
+	-re "fpu type:.*cause.*mask.*flags.*round.*flush.*f0:.*flt:.*dbl:.*$gdb_prompt $" {
+	      pass "info float (with FPU)"
+	  }
+    }
 } elseif [istarget "powerpc*-*-*"] then {
     gdb_test_multiple "info float" "info_float" {
         -re "f0.*f1.*f31.*fpscr.*$gdb_prompt $" {

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 2/3] Refactor gdbarch method print_float_info
  2014-12-18  1:02     ` Yao Qi
@ 2014-12-18 11:14       ` Pedro Alves
  0 siblings, 0 replies; 13+ messages in thread
From: Pedro Alves @ 2014-12-18 11:14 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 12/18/2014 01:01 AM, Yao Qi wrote:
> Thanks for the review.  Patch below is updated to address all your comments.

This looks good to me.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/3] MIPS: Provide FPU info and decode FCSR in `info float'
  2014-12-18  1:07       ` Yao Qi
@ 2014-12-18 11:16         ` Pedro Alves
  0 siblings, 0 replies; 13+ messages in thread
From: Pedro Alves @ 2014-12-18 11:16 UTC (permalink / raw)
  To: Yao Qi; +Cc: gdb-patches

On 12/18/2014 01:07 AM, Yao Qi wrote:
> Yao Qi <yao@codesourcery.com> writes:
> 
>>  } elseif [istarget "mips*-*-*"] then {
>> -    gdb_test "info float" "f0:.*flt:.*dbl:.*" "info float"
>> +    gdb_test_multiple "info float" "info float" {
>> +	-re "fpu type: none*" {
>> +	      pass "info float (without FPU)"
>> +	  }
>> +	-re "fpu type:.*cause.*mask.*flags.*round.*flush.*" {
>> +	      pass "info float (with FPU)"
>> +	  }
>> +    }
> 
> The updated patch adds the "$gdb_prompt $" at the end of those patterns
> and restrict the restrict the patterns.

Thanks, this version looks good to me.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 0/3, V2] MIPS: Provide FPU info and decode FCSR in `info float'
  2014-12-17  6:46 [PATCH 0/3, V2] MIPS: Provide FPU info and decode FCSR in `info float' Yao Qi
                   ` (2 preceding siblings ...)
  2014-12-17  6:46 ` [PATCH 2/3] Refactor gdbarch method print_float_info Yao Qi
@ 2014-12-18 12:52 ` Yao Qi
  3 siblings, 0 replies; 13+ messages in thread
From: Yao Qi @ 2014-12-18 12:52 UTC (permalink / raw)
  To: gdb-patches

Yao Qi <yao@codesourcery.com> writes:

> This patch series is the V2, to mainly address review comments in V1,
> which can be found in https://sourceware.org/ml/gdb-patches/2012-05/msg00938.html
>
> In the review to V1, Joel suggested to continue dumping float point
> registers in 'info float' and we do that in V2 by calling
> print_float_info's default implementation default_print_float_info.
>
> During writing this patch, I find h8300_print_float_info isn't needed.
> I remove it too.
>
> This patch series is tested under mips-linux-gnu.  Is it OK?

I've pushed them in.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH 3/3] MIPS: Provide FPU info and decode FCSR in `info float'
  2014-12-17 10:53   ` Pedro Alves
  2014-12-17 12:40     ` Yao Qi
@ 2014-12-21  0:14     ` Maciej W. Rozycki
  1 sibling, 0 replies; 13+ messages in thread
From: Maciej W. Rozycki @ 2014-12-21  0:14 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Yao Qi, gdb-patches

On Wed, 17 Dec 2014, Pedro Alves wrote:

> > +static void
> > +mips_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
> > +		      struct frame_info *frame, const char *args)
> > +{
> > +  int fcsr = mips_regnum (gdbarch)->fp_control_status;
> > +  enum mips_fpu_type type = MIPS_FPU_TYPE (gdbarch);
> > +  ULONGEST fcs = 0;
> > +  int i;
> > +
> > +  if (fcsr == -1 || !deprecated_frame_register_read (frame, fcsr, NULL))
> > +    type = MIPS_FPU_NONE;
> 
> "deprecated" method usage alert.  It's better to use methods that return
> values and then print "<unsaved>", "<unavailable>" as appropriate,
> though in this case you may be able to just use read_frame_register_unsigned
> instead.

 For the record, we use `get_frame_register_unsigned' in such cases 
elsewhere, e.g. `micromips_bc1_pc' and we don't expect it to fail on the 
assumption that `fp_control_status' will have been set correctly.  I see 
this change went in already, but I'd like to see it updated with a 
follow-up change for consistency.

 Specifically `get_frame_register_unsigned' is unsuitable here (as we want 
to poke at the actual register file, not the frame state), but I think a 
failure from `read_frame_register_unsigned' should be signalled as an 
error (exception being thrown, just as from the former function) rather 
than being silently treated as if there were no FPU.

 Also I think the registers should be dumped earlier on, with only generic 
FPU parameters preceding, as the extra decoded FCSR information is an 
elaboration of raw register contents, so I find it logical (as far as the 
reading flow of English text is considered) to be presented later, i.e.:

fpu type: ...
reg size: ...
[registers]
cond    : ...
[...]

Or so I think.  It would help reviewing it if the updated version of the 
patch was presented with corresponding output produced accompanying, just 
as I did with the original version.  Otherwise it requires drawing the 
output in one's head which is not necessarily straightforward.

  Maciej

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2014-12-21  0:14 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-17  6:46 [PATCH 0/3, V2] MIPS: Provide FPU info and decode FCSR in `info float' Yao Qi
2014-12-17  6:46 ` [PATCH 1/3] Remove h8300_print_float_info Yao Qi
2014-12-17  6:46 ` [PATCH 3/3] MIPS: Provide FPU info and decode FCSR in `info float' Yao Qi
2014-12-17 10:53   ` Pedro Alves
2014-12-17 12:40     ` Yao Qi
2014-12-18  1:07       ` Yao Qi
2014-12-18 11:16         ` Pedro Alves
2014-12-21  0:14     ` Maciej W. Rozycki
2014-12-17  6:46 ` [PATCH 2/3] Refactor gdbarch method print_float_info Yao Qi
2014-12-17 13:24   ` Pedro Alves
2014-12-18  1:02     ` Yao Qi
2014-12-18 11:14       ` Pedro Alves
2014-12-18 12:52 ` [PATCH 0/3, V2] MIPS: Provide FPU info and decode FCSR in `info float' Yao Qi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).