This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Printing decimal128 types out of registers


On Wed, 2008-01-30 at 22:24 +0100, Ulrich Weigand wrote:
> just a minor issue I noticed:
> 
> > +    return builtin_type (current_gdbarch)->builtin_declong;
> 
> Please use gdbarch instead of current_gdbarch here (and in a
> number other places) ...

Sorry about that. Fixed to use the gdbarch which is passed as parameter
to the functions and committed this patch.
-- 
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
2008-01-31  Luis Machado  <luisgpm@br.ibm.com>
	    Thiago Jung Bauermann  <bauerman@br.ibm.com>

gdb/
	* infcmd.c (default_print_registers_info): Also print hex
	raw contents for TYPE_CODE_DECFLOAT registers.
	* ppc-tdep.h (gdbarch_tdep): Add ppc_dl0_regnum member.
	* rs6000-tdep.c (IS_DFP_PSEUDOREG): New macro.
	(rs6000_register_name): Add support for DFP pseudo-registers.
	(rs6000_pseudo_register_type): Likewise.
	rs6000_pseudo_register_reggroup_p): Likewise.
	(ppc_pseudo_register_read): New function.
	(ppc_pseudo_register_write): Likewise.
	(rs6000_pseudo_register_read): Likewise.
	(rs6000_pseudo_register_write): Likewise.
	(e500_pseudo_register_read): Move checks to
	rs6000_pseudo_register_read.
	(e500_pseudo_register_write): Move checks to
	rs6000_pseudo_register_write.
	(rs6000_gdbarch_init): Initialize tdep->ppc_dl0_regnum.  Install
	rs6000_pseudo_register_read and rs6000_pseudo_register_write
	in gdbarch if SPE or DFP is available.  Adjust gdbarch's
	num_pseudo_regs to account for DFP pseudo regs.

gdb/testsuite/
	* gdb.arch/powerpc-d128-regs.exp: New testcase expect file.
	* gdb.arch/powerpc-d128-regs.c: New testcase source file.

gdb/doc/
	* gdb.texinfo: (Decimal Floating Point): Mention pseudo-registers
	available in PowerPC architecture.
	(Embedded Processors): Change node name of PowerPC item in menu.
	(PowerPC): Rename to...
	(PowerPC Embedded): this.
	(Architectures): Add new PowerPC item in menu.
	(PowerPC): New node.

diff -r 168620c4b9da -r 6587f6a67be2 gdb/doc/gdb.texinfo
--- a/gdb/doc/gdb.texinfo	Wed Jan 30 16:49:16 2008 -0200
+++ b/gdb/doc/gdb.texinfo	Thu Jan 31 11:16:39 2008 -0200
@@ -9670,6 +9670,10 @@ In addition, in order to imitate @value{
 In addition, in order to imitate @value{GDBN}'s behaviour with binary floating
 point computations, error checking in decimal float operations ignores
 underflow, overflow and divide by zero exceptions.
+
+In the PowerPC architecture, @value{GDBN} provides a set of pseudo-registers
+to inspect @code{_Decimal128} values stored in floating point registers. See
+@ref{PowerPC,,PowerPC} for more details.
 
 @node Objective-C
 @subsection Objective-C
@@ -14602,7 +14606,7 @@ acceptable commands.
 * MIPS Embedded::               MIPS Embedded
 * OpenRISC 1000::               OpenRisc 1000
 * PA::                          HP PA Embedded
-* PowerPC::                     PowerPC
+* PowerPC Embedded::            PowerPC Embedded
 * Sparclet::                    Tsqware Sparclet
 * Sparclite::                   Fujitsu Sparclite
 * Z8000::                       Zilog Z8000
@@ -15111,8 +15115,8 @@ Set suspend trace mode.
 
 @end table
 
-@node PowerPC
-@subsection PowerPC
+@node PowerPC Embedded
+@subsection PowerPC Embedded
 
 @value{GDBN} provides the following PowerPC-specific commands:
 
@@ -15475,6 +15479,7 @@ all uses of @value{GDBN} with the archit
 * MIPS::
 * HPPA::               HP PA architecture
 * SPU::                Cell Broadband Engine SPU architecture
+* PowerPC::
 @end menu
 
 @node i386
@@ -15691,6 +15696,20 @@ and local store addresses and transfer s
 
 @end table
  
+@node PowerPC
+@subsection PowerPC
+@cindex PowerPC architecture
+
+When @value{GDBN} is debugging the PowerPC architecture, it provides a set of 
+pseudo-registers to enable inspection of 128-bit wide Decimal Floating Point
+numbers stored in the floating point registers. These values must be stored
+in two consecutive registers, always starting at an even register like
+@code{f0} or @code{f2}.
+
+The pseudo-registers go from @code{$dl0} through @code{$dl15}, and are formed
+by joining the even/odd register pairs @code{f0} and @code{f1} for @code{$dl0},
+@code{f2} and @code{f3} for @code{$dl1} and so on.
+
 
 @node Controlling GDB
 @chapter Controlling @value{GDBN}
diff -r 168620c4b9da -r 6587f6a67be2 gdb/infcmd.c
--- a/gdb/infcmd.c	Wed Jan 30 16:49:16 2008 -0200
+++ b/gdb/infcmd.c	Thu Jan 31 11:16:39 2008 -0200
@@ -1624,7 +1624,8 @@ default_print_registers_info (struct gdb
 
       /* If virtual format is floating, print it that way, and in raw
          hex.  */
-      if (TYPE_CODE (register_type (gdbarch, i)) == TYPE_CODE_FLT)
+      if (TYPE_CODE (register_type (gdbarch, i)) == TYPE_CODE_FLT
+	  || TYPE_CODE (register_type (gdbarch, i)) == TYPE_CODE_DECFLOAT)
 	{
 	  int j;
 
diff -r 168620c4b9da -r 6587f6a67be2 gdb/ppc-tdep.h
--- a/gdb/ppc-tdep.h	Wed Jan 30 16:49:16 2008 -0200
+++ b/gdb/ppc-tdep.h	Thu Jan 31 11:16:39 2008 -0200
@@ -204,6 +204,9 @@ struct gdbarch_tdep
     int ppc_acc_regnum;         /* SPE 'acc' register */
     int ppc_spefscr_regnum;     /* SPE 'spefscr' register */
 
+    /* Decimal 128 registers.  */
+    int ppc_dl0_regnum;		/* First Decimal128 argument register pair.  */
+
     /* Offset to ABI specific location where link register is saved.  */
     int lr_frame_offset;	
 
diff -r 168620c4b9da -r 6587f6a67be2 gdb/rs6000-tdep.c
--- a/gdb/rs6000-tdep.c	Wed Jan 30 16:49:16 2008 -0200
+++ b/gdb/rs6000-tdep.c	Thu Jan 31 11:16:39 2008 -0200
@@ -82,6 +82,11 @@
 #define IS_SPE_PSEUDOREG(tdep, regnum) ((tdep)->ppc_ev0_regnum >= 0 \
     && (regnum) >= (tdep)->ppc_ev0_regnum \
     && (regnum) < (tdep)->ppc_ev0_regnum + 32)
+
+/* Determine if regnum is a decimal float pseudo-register.  */
+#define IS_DFP_PSEUDOREG(tdep, regnum) ((tdep)->ppc_dl0_regnum >= 0 \
+    && (regnum) >= (tdep)->ppc_dl0_regnum \
+    && (regnum) < (tdep)->ppc_dl0_regnum + 16)
 
 /* The list of available "set powerpc ..." and "show powerpc ..."
    commands.  */
@@ -2385,6 +2390,18 @@ rs6000_register_name (struct gdbarch *gd
       return spe_regnames[regno - tdep->ppc_ev0_regnum];
     }
 
+  /* Check if the decimal128 pseudo-registers are available.  */
+  if (IS_DFP_PSEUDOREG (tdep, regno))
+    {
+      static const char *const dfp128_regnames[] = {
+	"dl0", "dl1", "dl2", "dl3",
+	"dl4", "dl5", "dl6", "dl7",
+	"dl8", "dl9", "dl10", "dl11",
+	"dl12", "dl13", "dl14", "dl15"
+      };
+      return dfp128_regnames[regno - tdep->ppc_dl0_regnum];
+    }
+
   return tdesc_register_name (gdbarch, regno);
 }
 
@@ -2397,9 +2414,15 @@ rs6000_pseudo_register_type (struct gdba
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   /* These are the only pseudo-registers we support.  */
-  gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum));
+  gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
+	      || IS_DFP_PSEUDOREG (tdep, regnum));
 
-  return rs6000_builtin_type_vec64 (gdbarch);
+  /* These are the e500 pseudo-registers.  */
+  if (IS_SPE_PSEUDOREG (tdep, regnum))
+    return rs6000_builtin_type_vec64 (gdbarch);
+  else
+    /* Could only be the ppc decimal128 pseudo-registers.  */
+    return builtin_type (gdbarch)->builtin_declong;
 }
 
 /* Is REGNUM a member of REGGROUP?  */
@@ -2410,12 +2433,15 @@ rs6000_pseudo_register_reggroup_p (struc
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   /* These are the only pseudo-registers we support.  */
-  gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum));
+  gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
+	      || IS_DFP_PSEUDOREG (tdep, regnum));
 
-  if (group == all_reggroup || group == vector_reggroup)
-    return 1;
+  /* These are the e500 pseudo-registers.  */
+  if (IS_SPE_PSEUDOREG (tdep, regnum))
+    return group == all_reggroup || group == vector_reggroup;
   else
-    return 0;
+    /* Could only be the ppc decimal128 pseudo-registers.  */
+    return group == all_reggroup || group == float_reggroup;
 }
 
 /* The register format for RS/6000 floating point registers is always
@@ -2516,38 +2542,110 @@ e500_pseudo_register_read (struct gdbarc
 e500_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
 			   int reg_nr, gdb_byte *buffer)
 {
-  struct gdbarch *regcache_arch = get_regcache_arch (regcache);
-  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 
-
-  gdb_assert (regcache_arch == gdbarch);
- 
-  if (IS_SPE_PSEUDOREG (tdep, reg_nr))
-    e500_move_ev_register (regcache_raw_read, regcache, reg_nr, buffer);
-  else
-    internal_error (__FILE__, __LINE__,
-                    _("e500_pseudo_register_read: "
-                    "called on unexpected register '%s' (%d)"),
-                    gdbarch_register_name (gdbarch, reg_nr), reg_nr);
+  e500_move_ev_register (regcache_raw_read, regcache, reg_nr, buffer);
 }
 
 static void
 e500_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
 			    int reg_nr, const gdb_byte *buffer)
 {
+  e500_move_ev_register ((void (*) (struct regcache *, int, gdb_byte *))
+			 regcache_raw_write,
+			 regcache, reg_nr, (gdb_byte *) buffer);
+}
+
+/* Read method for PPC pseudo-registers. Currently this is handling the
+   16 decimal128 registers that map into 16 pairs of FP registers.  */
+static void
+ppc_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+			   int reg_nr, gdb_byte *buffer)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int reg_index = reg_nr - tdep->ppc_dl0_regnum;
+
+  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+    {
+      /* Read two FP registers to form a whole dl register.  */
+      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+			 2 * reg_index, buffer);
+      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+			 2 * reg_index + 1, buffer + 8);
+    }
+  else
+    {
+      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+			 2 * reg_index + 1, buffer + 8);
+      regcache_raw_read (regcache, tdep->ppc_fp0_regnum +
+			 2 * reg_index, buffer);
+    }
+}
+
+/* Write method for PPC pseudo-registers. Currently this is handling the
+   16 decimal128 registers that map into 16 pairs of FP registers.  */
+static void
+ppc_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+			    int reg_nr, const gdb_byte *buffer)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  int reg_index = reg_nr - tdep->ppc_dl0_regnum;
+
+  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+    {
+      /* Write each half of the dl register into a separate
+      FP register.  */
+      regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+			  2 * reg_index, buffer);
+      regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+			  2 * reg_index + 1, buffer + 8);
+    }
+  else
+    {
+      regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+			  2 * reg_index + 1, buffer + 8);
+      regcache_raw_write (regcache, tdep->ppc_fp0_regnum +
+			  2 * reg_index, buffer);
+    }
+}
+
+static void
+rs6000_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
+			     int reg_nr, gdb_byte *buffer)
+{
   struct gdbarch *regcache_arch = get_regcache_arch (regcache);
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 
 
   gdb_assert (regcache_arch == gdbarch);
- 
+
   if (IS_SPE_PSEUDOREG (tdep, reg_nr))
-    e500_move_ev_register ((void (*) (struct regcache *, int, gdb_byte *))
-                           regcache_raw_write,
-                           regcache, reg_nr, (gdb_byte *) buffer);
+    e500_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
+    ppc_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
   else
     internal_error (__FILE__, __LINE__,
-                    _("e500_pseudo_register_read: "
-                    "called on unexpected register '%s' (%d)"),
-                    gdbarch_register_name (gdbarch, reg_nr), reg_nr);
+		    _("rs6000_pseudo_register_read: "
+		    "called on unexpected register '%s' (%d)"),
+		    gdbarch_register_name (gdbarch, reg_nr), reg_nr);
+}
+
+static void
+rs6000_pseudo_register_write (struct gdbarch *gdbarch,
+			      struct regcache *regcache,
+			      int reg_nr, const gdb_byte *buffer)
+{
+  struct gdbarch *regcache_arch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 
+
+  gdb_assert (regcache_arch == gdbarch);
+
+  if (IS_SPE_PSEUDOREG (tdep, reg_nr))
+    e500_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
+    ppc_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+  else
+    internal_error (__FILE__, __LINE__,
+		    _("rs6000_pseudo_register_write: "
+		    "called on unexpected register '%s' (%d)"),
+		    gdbarch_register_name (gdbarch, reg_nr), reg_nr);
 }
 
 /* Convert a DBX STABS register number to a GDB register number.  */
@@ -3168,10 +3266,11 @@ rs6000_gdbarch_init (struct gdbarch_info
   enum auto_boolean soft_float_flag = powerpc_soft_float_global;
   int soft_float;
   enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global;
-  int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0;
+  int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0;
   int tdesc_wordsize = -1;
   const struct target_desc *tdesc = info.target_desc;
   struct tdesc_arch_data *tdesc_data = NULL;
+  int num_pseudoregs = 0;
 
   from_xcoff_exec = info.abfd && info.abfd->format == bfd_object &&
     bfd_get_flavour (info.abfd) == bfd_target_xcoff_flavour;
@@ -3341,6 +3440,10 @@ rs6000_gdbarch_init (struct gdbarch_info
 	}
       else
 	have_fpu = 0;
+
+      /* The DFP pseudo-registers will be available when there are floating
+         point registers.  */
+      have_dfp = have_fpu;
 
       feature = tdesc_find_feature (tdesc,
 				    "org.gnu.gdb.power.altivec");
@@ -3588,10 +3691,10 @@ rs6000_gdbarch_init (struct gdbarch_info
   else
     tdep->lr_frame_offset = 8;
 
-  if (have_spe)
+  if (have_spe || have_dfp)
     {
-      set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read);
-      set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write);
+      set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read);
+      set_gdbarch_pseudo_register_write (gdbarch, rs6000_pseudo_register_write);
     }
 
   set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
@@ -3603,7 +3706,13 @@ rs6000_gdbarch_init (struct gdbarch_info
     set_gdbarch_print_insn (gdbarch, gdb_print_insn_powerpc);
 
   set_gdbarch_num_regs (gdbarch, PPC_NUM_REGS);
-  set_gdbarch_num_pseudo_regs (gdbarch, have_spe ? 32 : 0);
+
+  if (have_spe)
+    num_pseudoregs += 32;
+  if (have_dfp)
+    num_pseudoregs += 16;
+
+  set_gdbarch_num_pseudo_regs (gdbarch, num_pseudoregs);
 
   set_gdbarch_ptr_bit (gdbarch, wordsize * TARGET_CHAR_BIT);
   set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
@@ -3726,6 +3835,13 @@ rs6000_gdbarch_init (struct gdbarch_info
   /* Recording the numbering of pseudo registers.  */
   tdep->ppc_ev0_regnum = have_spe ? gdbarch_num_regs (gdbarch) : -1;
 
+  /* Set the register number for _Decimal128 pseudo-registers.  */
+  tdep->ppc_dl0_regnum = have_dfp? gdbarch_num_regs (gdbarch) : -1;
+
+  if (have_dfp && have_spe)
+    /* Put the _Decimal128 pseudo-registers after the SPE registers.  */
+    tdep->ppc_dl0_regnum += 32;
+
   return gdbarch;
 }
 
diff -r 168620c4b9da -r 6587f6a67be2 gdb/testsuite/gdb.arch/powerpc-d128-regs.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gdb/testsuite/gdb.arch/powerpc-d128-regs.c	Thu Jan 31 11:16:39 2008 -0200
@@ -0,0 +1,25 @@
+/* This file is part of GDB, the GNU debugger.
+
+   Copyright 2008 Free Software Foundation, Inc.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Tests ppc decimal128 pseudo-registers.  */
+
+int main(void)
+{
+  _Decimal128 d128 = 1.2345678910dl;
+
+  return 0;
+}
diff -r 168620c4b9da -r 6587f6a67be2 gdb/testsuite/gdb.arch/powerpc-d128-regs.exp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp	Thu Jan 31 11:16:39 2008 -0200
@@ -0,0 +1,77 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2008
+# Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@gnu.org
+
+# Testcase for ppc decimal128 pseudo-registers.
+
+if $tracelevel then {
+        strace $tracelevel
+}
+
+if ![istarget "powerpc64-*"] then {
+    verbose "Skipping powerpc Decimal128 pseudo-registers testcase."
+    return
+}
+
+set testfile "powerpc-d128-regs"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {quiet debug}] != "" } {
+     untested powerpc-d128-regs.exp
+     return -1
+}
+
+# Start with a fresh gdb.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+
+if { ![runto main] } then {
+   fail "run to main"
+   return
+}
+
+if [gdb_test "show arch" ".*currently powerpc:common.*" "Checking for PPC arch"] {
+    return -1;
+}
+
+gdb_test "next" ""
+
+for {set i 0} {$i < 16} {incr i 1} {
+gdb_test "set \$dl$i=d128" "" "Set dl$i register"
+
+gdb_test "print \$dl$i" "\\\$$decimal = 1\.2345678910" "Print dl$i register as DFP"
+
+gdb_test "info reg dl$i" \
+	 "dl$i\[ \]*1\.2345678910\[\t\]*\\(raw 0x2205800000000000000000049c5de09c\\)" \
+	 "Print dl$i register with the info reg command"
+
+gdb_test "info reg f[expr 2*$i]" \
+	 "f[expr 2*$i]\[ \]*8\.608957309287334e\-145\[\t\]*\\(raw 0x2205800000000000\\)" \
+	 "Testing lower half of dl$i register"
+
+gdb_test "info reg f[expr 2*$i+1]" \
+	 "f[expr 2*$i+1]\[ \]*9\.7841140127686122e\-314\[\t\]*\\(raw 0x000000049c5de09c\\)" \
+	 "Testing upper half of dl$i register"
+
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]