Re: Printing decimal128 types out of registers

Thiago Jung Bauermann
2008-01-30T15:17:25Z

[-- Attachment #1: Type: text/plain, Size: 1866 bytes --]

On Wed, 2008-01-23 at 10:20 -0500, Daniel Jacobowitz wrote:
> On Wed, Jan 23, 2008 at 01:10:38PM -0200, Thiago Jung Bauermann wrote:
> > > So I suggest we not have $dl0 except on
> > > hardware where the GDB user might look at the next instruction, see
> > > that it operates on register dl0, and want to check the value of that
> > > register.

<snip>

> If this is too complicated, I wouldn't argue against a patch that just
> added them if the floating point regsiters are present. Seems like it
> won't be useful on a lot of processors though.

Actually, this option is more appropriate. I have recently learned that
there are some regular float instructions which can be directly used in
DFP values stored in FP registers, like fabs, fneg and the other
floating point move instructions. So it is very useful to have the
pseudo-registers around even without specific DFP hardware.

The attached patch is a rework of Luis' patch, with the following
modifications:

- don't use tdesc XML machinery to define the DFP pseudo-regs;
- fixed logic in rs6000_pseudo_register_reggroup_p as noted by Daniel;
- put DFP pseudo-regs in float register group;
- the DFP pseudo-regs don't show up if there's no FPU;
- reorganized the pseudo_register_{read,write} functions: there's now
a generic one which concentrates the gdb_asserts and checking, and
calls either the SPE or DFP as appropriate.
- documentation: mention the DFP pseudo-regs in the Decimal Floating
Point subsection, and created a PowerPC architecture subsection to
talk about them in more detail. I had to rename the PowerPC Embedded
section to avoid a node name conflict.

This patch is on top of the SPE macro cleanup patch which I just posted:

http://sourceware.org/ml/gdb-patches/2008-01/msg00794.html

Is this ok?
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center

[-- Attachment #2: dec128-regs.diff --]
[-- Type: text/x-patch, Size: 19437 bytes --]

2008-01-30 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, ppc_dl15_regnum
and ppc_dl0_upper_regnum members.
* 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_upper_regnum,
tdep->ppc_dl0_regnum and ppc_dl15_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 acb978e1aa00 -r 1340ec73fb1c gdb/doc/gdb.texinfo
--- a/gdb/doc/gdb.texinfo Tue Jan 29 02:01:12 2008 -0200
+++ b/gdb/doc/gdb.texinfo Wed Jan 30 12:59:26 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 acb978e1aa00 -r 1340ec73fb1c gdb/infcmd.c
--- a/gdb/infcmd.c Tue Jan 29 02:01:12 2008 -0200
+++ b/gdb/infcmd.c Wed Jan 30 12:59:26 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 acb978e1aa00 -r 1340ec73fb1c gdb/ppc-tdep.h
--- a/gdb/ppc-tdep.h Tue Jan 29 02:01:12 2008 -0200
+++ b/gdb/ppc-tdep.h Wed Jan 30 12:59:26 2008 -0200
@@ -205,6 +205,11 @@ 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. */
+ int ppc_dl15_regnum; /* Last Decimal128 argument register pair. */
+ int ppc_dl0_upper_regnum; /* First FPR upper half register for dl0. */
+
/* Offset to ABI specific location where link register is saved. */
int lr_frame_offset;

diff -r acb978e1aa00 -r 1340ec73fb1c gdb/rs6000-tdep.c
--- a/gdb/rs6000-tdep.c Tue Jan 29 02:01:12 2008 -0200
+++ b/gdb/rs6000-tdep.c Wed Jan 30 12:59:26 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 (current_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 (current_gdbarch) == BFD_ENDIAN_BIG)
+ {
+ /* Read two FP registers to form a whole dl register. */
+ regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index, buffer);
+ regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, buffer + 8);
+ }
+ else
+ {
+ regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, buffer + 8);
+ regcache_raw_read (regcache, tdep->ppc_dl0_upper_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 (current_gdbarch) == BFD_ENDIAN_BIG)
+ {
+ /* Write each half of the dl register into a separate
+ FP register. */
+ regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index, buffer);
+ regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, buffer + 8);
+ }
+ else
+ {
+ regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, buffer + 8);
+ regcache_raw_write (regcache, tdep->ppc_dl0_upper_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,11 +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_sprs = 0;
+ int num_sprs = 0, num_pseudoregs = 0;

from_xcoff_exec = info.abfd && info.abfd->format == bfd_object &&
bfd_get_flavour (info.abfd) == bfd_target_xcoff_flavour;
@@ -3342,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");
@@ -3562,6 +3664,7 @@ rs6000_gdbarch_init (struct gdbarch_info
tdep->ppc_ev0_upper_regnum = have_spe ? PPC_SPE_UPPER_GP0_REGNUM : -1;
tdep->ppc_acc_regnum = have_spe ? PPC_SPE_ACC_REGNUM : -1;
tdep->ppc_spefscr_regnum = have_spe ? PPC_SPE_FSCR_REGNUM : -1;
+ tdep->ppc_dl0_upper_regnum = have_dfp ? PPC_F0_REGNUM : -1;

set_gdbarch_pc_regnum (gdbarch, PPC_PC_REGNUM);
set_gdbarch_sp_regnum (gdbarch, PPC_R0_REGNUM + 1);
@@ -3589,10 +3692,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);
@@ -3604,7 +3707,13 @@ rs6000_gdbarch_init (struct gdbarch_info
set_gdbarch_print_insn (gdbarch, gdb_print_insn_powerpc);

set_gdbarch_num_regs (gdbarch, PPC_NUM_REGS + num_sprs);
- 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);
@@ -3728,6 +3837,17 @@ rs6000_gdbarch_init (struct gdbarch_info
tdep->ppc_ev0_regnum = have_spe ? gdbarch_num_regs (gdbarch) : -1;
tdep->ppc_ev31_regnum = have_spe ? tdep->ppc_ev0_regnum + 31 : -1;

+ /* Set the register number for _Decimal128 pseudo-registers. */
+ tdep->ppc_dl0_regnum = have_dfp? gdbarch_num_regs (gdbarch) : -1;
+ tdep->ppc_dl15_regnum = have_dfp? tdep->ppc_dl0_regnum + 15 : -1;
+
+ if (have_dfp && have_spe)
+ {
+ /* Put the _Decimal128 pseudo-registers after the SPE registers. */
+ tdep->ppc_dl0_regnum += 32;
+ tdep->ppc_dl15_regnum += 32;
+ }
+
return gdbarch;
}

diff -r acb978e1aa00 -r 1340ec73fb1c 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 Wed Jan 30 12:59:26 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 acb978e1aa00 -r 1340ec73fb1c 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 Wed Jan 30 12:59:26 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"
+
+}