* [PATCH] PPC - Printing Decimal 128 types out of registers
@ 2007-11-07 19:33 Luis Machado
2007-11-26 21:40 ` Luis Machado
2008-01-17 19:03 ` Printing decimal128 " Luis Machado
0 siblings, 2 replies; 31+ messages in thread
From: Luis Machado @ 2007-11-07 19:33 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1910 bytes --]
Hi folks,
I'm continuing the work to enhance DFP type support on GDB. DFP types
are nativelly supported on the Power6 processor, thus they are stored in
registers as so. This patch handles the printing and setting of
Decimal128 types directly out of/in the registers.
A Decimal128 type is stored using pairs of Floating Point registers, and
it always starts in an even-numbered register. So, we could, for
example, have a Decimal128 var taking up FPR0-FPR1, FPR10-FPR11, but
never FPR1-FPR2 or FPR23-24.
Right now GDB isn't able to print those vars as it doesn't know they
take up more than one register.
The idea to overcome this was to create a new set of 16 Decimal128-typed
pseudo-registers called DL (Standing for "D"ecimal "L"ong Double) that
would represent all 16 pairs of Floating Point Registers.. By using a
pseudo-register mechanism, we're able to force the DL/FPR registers to
map directly into the FPR/DL registers.
Benefits of this change include:
* Better printing support for Decimal128 types. We just print the
register as is. No need to include casting tricks and arrays to print
that value.
* Straightforward way of setting Decimal128 values directly in the
registers. We just "set $dl0=1.23dl", for example, and it's
automatically set.
* Overview of the state of 16 Decimal128 registers using the "info reg
all" command.
Supporting the patch there is also a number of other modifications, as
listed:
* DFP types are now global since they were included as predefined types
in the "target-descriptions.c" file.
* A simple testcase making sure the registers are working as expected.
* Piece of documentation for the GDB manual.
* Fix to display a 128-bit hex literal representation of Decimal128
types (using "info reg").
Also note that this support will be available for both ppc64 and ppc32.
Looking forward to have comments and suggestions for improvements.
Regards,
Luis
[-- Attachment #2: registers-dfp.diff --]
[-- Type: text/x-patch, Size: 21123 bytes --]
2007-11-07 Luis Machado <luisgpm@br.ibm.com>
* rs6000-tdep.c (rs6000_gdbarch_init): Add support for
Decimal128 pseudo-registers.
(rs6000_pseudo_register_type): Returns the correct type for
Decimal128 pseudo-registers.
(rs6000_pseudo_register_reggroup_p): Returns the correct register
group for Decimal128 pseudo-registers.
(ppc_pseudo_register_read): New function.
(ppc_pseudo_register_write): New function.
* ppc-tdep.h: Add new variables ppc_dl0_upper_regnum, ppc_dl0_regnum
and ppc_dl15_regnum.
* target-descriptions.c: Add new predefined DFP types.
* c-exp.y: Fix DFP type names.
* gdbtypes.c (_initialize_gdbtypes): Initialize new global
DFP types.
* gdbtypes.h: Declare new global DFP types and remove the old ones.
* printcmd.c: Fix displaying of DFP types as hex.
* features/rs6000/powerpc-64.c (initialize_tdesc_powerpc_64): Create
a new feature for Decimal128 pseudo-registers.
* features/rs6000/powerpc-32.c (initialize_tdesc_powerpc_32): Create
a new feature for Decimal128 pseudo-registers.
* testsuite/gdb.arch/powerpc-d128-regs.exp: New testcase expect
file.
* testsuite/gdb.arch/powerpc-d128-regs.c: New testcase source
file.
* doc/gdb.textinfo: Add new powerpc dfp128 feature documentation.
Index: git/gdb/rs6000-tdep.c
===================================================================
--- git.orig/gdb/rs6000-tdep.c 2007-11-05 11:37:24.000000000 -0800
+++ git/gdb/rs6000-tdep.c 2007-11-07 07:43:50.000000000 -0800
@@ -2381,6 +2381,20 @@
return spe_regnames[regno - tdep->ppc_ev0_regnum];
}
+ /* Check if the Decimal128 pseudo-registers are available. */
+ if (tdep->ppc_dl0_regnum >= 0
+ && tdep->ppc_dl0_regnum <= regno
+ && regno < tdep->ppc_dl0_regnum + 16)
+ {
+ 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);
}
@@ -2392,12 +2406,19 @@
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- /* These are the only pseudo-registers we support. */
- gdb_assert (tdep->ppc_ev0_regnum >= 0
- && regnum >= tdep->ppc_ev0_regnum
- && regnum < tdep->ppc_ev0_regnum + 32);
+ /* These are the e500 pseudo-registers. */
+ if (tdep->ppc_ev0_regnum >= 0
+ && regnum >= tdep->ppc_ev0_regnum
+ && regnum < tdep->ppc_ev0_regnum + 32)
+ return rs6000_builtin_type_vec64 (gdbarch);
+
+ /* These are the ppc Decimal128 pseudo-registers. */
+ if (tdep->ppc_dl0_regnum >= 0
+ && regnum >= tdep->ppc_dl0_regnum
+ && regnum < tdep->ppc_dl0_regnum + 16)
+ return builtin_type_declong;
- return rs6000_builtin_type_vec64 (gdbarch);
+ return NULL;
}
/* Is REGNUM a member of REGGROUP? */
@@ -2407,10 +2428,16 @@
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- /* These are the only pseudo-registers we support. */
- gdb_assert (tdep->ppc_ev0_regnum >= 0
- && regnum >= tdep->ppc_ev0_regnum
- && regnum < tdep->ppc_ev0_regnum + 32);
+ /* These are the e500 pseudo-registers. */
+ if (tdep->ppc_ev0_regnum < 0
+ && regnum < tdep->ppc_ev0_regnum
+ && regnum >= tdep->ppc_ev0_regnum + 32)
+ return -1;
+
+ if (tdep->ppc_dl0_regnum < 0
+ && regnum < tdep->ppc_dl0_regnum
+ && regnum >= tdep->ppc_dl0_regnum + 16)
+ return -1;
if (group == all_reggroup || group == vector_reggroup)
return 1;
@@ -2552,6 +2579,89 @@
gdbarch_register_name (gdbarch, reg_nr), reg_nr);
}
+/* Read method for PPC pseudo-registers. Currently this is handling the
+ 16 Decimal 128 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 *regcache_arch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int reg_index;
+ gdb_byte *byte_buffer = buffer;
+
+ gdb_assert (regcache_arch == gdbarch);
+
+ if (tdep->ppc_dl0_regnum <= reg_nr
+ && reg_nr < tdep->ppc_dl0_regnum + 16)
+ {
+ 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, byte_buffer);
+ regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, byte_buffer + 8);
+ }
+ else
+ {
+ regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, byte_buffer + 8);
+ regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index, byte_buffer);
+ }
+ }
+ else
+ internal_error (__FILE__, __LINE__,
+ _("ppc_pseudo_register_read: "
+ "called on unexpected register '%s' (%d)"),
+ gdbarch_register_name (gdbarch, reg_nr), reg_nr);
+}
+
+/* Write method for PPC pseudo-registers. Currently this is handling the
+ 16 Decimal 128 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 *regcache_arch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int reg_index;
+ const gdb_byte *byte_buffer = buffer;
+
+ gdb_assert (regcache_arch == gdbarch);
+
+ if (tdep->ppc_dl0_regnum <= reg_nr
+ && reg_nr < tdep->ppc_dl0_regnum + 16)
+ {
+ 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, byte_buffer);
+ regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, byte_buffer + 8);
+ }
+ else
+ {
+ regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, byte_buffer + 8);
+ regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index, byte_buffer);
+ }
+ }
+ else
+ internal_error (__FILE__, __LINE__,
+ _("ppc_pseudo_register_read: "
+ "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. */
static int
rs6000_stab_reg_to_regnum (int num)
@@ -3170,7 +3280,8 @@
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_dfp128 = 0;
int tdesc_wordsize = -1;
const struct target_desc *tdesc = info.target_desc;
struct tdesc_arch_data *tdesc_data = NULL;
@@ -3376,6 +3487,12 @@
else
have_altivec = 0;
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.dfp128");
+
+ if (feature != NULL)
+ have_dfp128 = 1;
+
/* On machines supporting the SPE APU, the general-purpose registers
are 64 bits long. There are SIMD vector instructions to treat them
as pairs of floats, but the rest of the instruction set treats them
@@ -3564,6 +3681,7 @@
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_dfp128 ? PPC_F0_REGNUM : -1;
set_gdbarch_pc_regnum (gdbarch, PPC_PC_REGNUM);
set_gdbarch_sp_regnum (gdbarch, PPC_R0_REGNUM + 1);
@@ -3596,6 +3714,12 @@
set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write);
}
+ else
+ if (have_dfp128)
+ {
+ set_gdbarch_pseudo_register_read (gdbarch, ppc_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch, ppc_pseudo_register_write);
+ }
set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
@@ -3606,7 +3730,12 @@
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)
+ set_gdbarch_num_pseudo_regs (gdbarch, 32);
+ else
+ if (have_dfp128)
+ set_gdbarch_num_pseudo_regs (gdbarch, 16);
set_gdbarch_ptr_bit (gdbarch, wordsize * TARGET_CHAR_BIT);
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
@@ -3730,6 +3859,10 @@
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_dfp128 ? gdbarch_num_regs (gdbarch) : -1;
+ tdep->ppc_dl15_regnum = have_dfp128 ? tdep->ppc_dl0_regnum + 15 : -1;
+
return gdbarch;
}
Index: git/gdb/ppc-tdep.h
===================================================================
--- git.orig/gdb/ppc-tdep.h 2007-11-05 11:37:24.000000000 -0800
+++ git/gdb/ppc-tdep.h 2007-11-06 04:20:22.000000000 -0800
@@ -205,6 +205,11 @@
int ppc_acc_regnum; /* SPE 'acc' register */
int ppc_spefscr_regnum; /* SPE 'spefscr' register */
+ /* Decimal 128 registers. */
+ int ppc_dl0_regnum; /* First Decimal128 register pair. */
+ int ppc_dl15_regnum; /* Last Decimal128 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;
Index: git/gdb/printcmd.c
===================================================================
--- git.orig/gdb/printcmd.c 2007-11-06 04:20:21.000000000 -0800
+++ git/gdb/printcmd.c 2007-11-06 04:20:22.000000000 -0800
@@ -326,7 +326,8 @@
if (len > sizeof(LONGEST) &&
(TYPE_CODE (type) == TYPE_CODE_INT
- || TYPE_CODE (type) == TYPE_CODE_ENUM))
+ || TYPE_CODE (type) == TYPE_CODE_ENUM
+ || TYPE_CODE (type) == TYPE_CODE_DECFLOAT))
{
switch (format)
{
Index: git/gdb/target-descriptions.c
===================================================================
--- git.orig/gdb/target-descriptions.c 2007-11-05 11:37:24.000000000 -0800
+++ git/gdb/target-descriptions.c 2007-11-06 04:20:22.000000000 -0800
@@ -360,7 +360,10 @@
{ "uint128", &builtin_type_uint128 },
{ "ieee_single", &builtin_type_ieee_single },
{ "ieee_double", &builtin_type_ieee_double },
- { "arm_fpa_ext", &builtin_type_arm_ext }
+ { "arm_fpa_ext", &builtin_type_arm_ext },
+ { "decfloat", &builtin_type_decfloat },
+ { "decdouble", &builtin_type_decdouble },
+ { "declong", &builtin_type_declong }
};
/* Return the type associated with ID in the context of FEATURE, or
Index: git/gdb/c-exp.y
===================================================================
--- git.orig/gdb/c-exp.y 2007-11-05 11:37:24.000000000 -0800
+++ git/gdb/c-exp.y 2007-11-06 04:20:22.000000000 -0800
@@ -1098,7 +1098,7 @@
{
p[len - 2] = '\0';
putithere->typed_val_decfloat.type
- = builtin_type (current_gdbarch)->builtin_decfloat;
+ = builtin_type_decfloat;
decimal_from_string (putithere->typed_val_decfloat.val, 4, p);
p[len] = saved_char;
return (DECFLOAT);
@@ -1108,7 +1108,7 @@
{
p[len - 2] = '\0';
putithere->typed_val_decfloat.type
- = builtin_type (current_gdbarch)->builtin_decdouble;
+ = builtin_type_decdouble;
decimal_from_string (putithere->typed_val_decfloat.val, 8, p);
p[len] = saved_char;
return (DECFLOAT);
@@ -1118,7 +1118,7 @@
{
p[len - 2] = '\0';
putithere->typed_val_decfloat.type
- = builtin_type (current_gdbarch)->builtin_declong;
+ = builtin_type_declong;
decimal_from_string (putithere->typed_val_decfloat.val, 16, p);
p[len] = saved_char;
return (DECFLOAT);
Index: git/gdb/gdbtypes.c
===================================================================
--- git.orig/gdb/gdbtypes.c 2007-11-05 11:37:24.000000000 -0800
+++ git/gdb/gdbtypes.c 2007-11-07 06:40:37.000000000 -0800
@@ -103,7 +103,9 @@
struct type *builtin_type_arm_ext;
struct type *builtin_type_ia64_spill;
struct type *builtin_type_ia64_quad;
-
+struct type *builtin_type_decfloat;
+struct type *builtin_type_decdouble;
+struct type *builtin_type_declong;
int opaque_type_resolution = 1;
static void
@@ -3172,21 +3174,6 @@
0,
"bool", (struct objfile *) NULL);
- /* The following three are about decimal floating point types, which
- are 32-bits, 64-bits and 128-bits respectively. */
- builtin_type->builtin_decfloat
- = init_type (TYPE_CODE_DECFLOAT, 32 / 8,
- 0,
- "decimal float", (struct objfile *) NULL);
- builtin_type->builtin_decdouble
- = init_type (TYPE_CODE_DECFLOAT, 64 / 8,
- 0,
- "decimal double", (struct objfile *) NULL);
- builtin_type->builtin_declong
- = init_type (TYPE_CODE_DECFLOAT, 128 / 8,
- 0,
- "decimal long double", (struct objfile *) NULL);
-
/* Pointer/Address types. */
/* NOTE: on some targets, addresses and pointers are not necessarily
@@ -3305,6 +3292,21 @@
TYPE_FLAG_UNSIGNED,
"uint128_t", (struct objfile *) NULL);
+ builtin_type_decfloat
+ = init_type (TYPE_CODE_DECFLOAT, 32 / 8,
+ 0,
+ "decimal float", (struct objfile *) NULL);
+
+ builtin_type_decdouble
+ = init_type (TYPE_CODE_DECFLOAT, 64 / 8,
+ 0,
+ "decimal double", (struct objfile *) NULL);
+
+ builtin_type_declong
+ = init_type (TYPE_CODE_DECFLOAT, 128 / 8,
+ 0,
+ "decimal long double", (struct objfile *) NULL);
+
builtin_type_ieee_single =
build_flt (-1, "builtin_type_ieee_single", floatformats_ieee_single);
builtin_type_ieee_double =
Index: git/gdb/gdbtypes.h
===================================================================
--- git.orig/gdb/gdbtypes.h 2007-11-05 11:37:24.000000000 -0800
+++ git/gdb/gdbtypes.h 2007-11-07 06:41:15.000000000 -0800
@@ -1016,9 +1016,6 @@
struct type *builtin_bool;
struct type *builtin_long_long;
struct type *builtin_unsigned_long_long;
- struct type *builtin_decfloat;
- struct type *builtin_decdouble;
- struct type *builtin_declong;
};
/* Return the type table for the specified architecture. */
@@ -1107,6 +1104,9 @@
extern struct type *builtin_type_arm_ext;
extern struct type *builtin_type_ia64_spill;
extern struct type *builtin_type_ia64_quad;
+extern struct type *builtin_type_decfloat;
+extern struct type *builtin_type_decdouble;
+extern struct type *builtin_type_declong;
/* This type represents a type that was unrecognized in symbol
read-in. */
Index: git/gdb/features/rs6000/powerpc-64.c
===================================================================
--- git.orig/gdb/features/rs6000/powerpc-64.c 2007-11-05 11:37:24.000000000 -0800
+++ git/gdb/features/rs6000/powerpc-64.c 2007-11-06 04:20:22.000000000 -0800
@@ -160,5 +160,7 @@
tdesc_create_reg (feature, "vscr", 103, 1, "vector", 32, "int");
tdesc_create_reg (feature, "vrsave", 104, 1, "vector", 32, "int");
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.dfp128");
+
tdesc_powerpc_64 = result;
}
Index: git/gdb/features/rs6000/powerpc-32.c
===================================================================
--- git.orig/gdb/features/rs6000/powerpc-32.c 2007-10-21 12:33:37.000000000 -0700
+++ git/gdb/features/rs6000/powerpc-32.c 2007-11-07 06:52:18.000000000 -0800
@@ -160,5 +160,7 @@
tdesc_create_reg (feature, "vscr", 103, 1, "vector", 32, "int");
tdesc_create_reg (feature, "vrsave", 104, 1, "vector", 32, "int");
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.dfp128");
+
tdesc_powerpc_32 = result;
}
Index: git/gdb/doc/gdb.texinfo
===================================================================
--- git.orig/gdb/doc/gdb.texinfo 2007-11-06 04:20:21.000000000 -0800
+++ git/gdb/doc/gdb.texinfo 2007-11-07 07:12:34.000000000 -0800
@@ -26322,6 +26322,13 @@
these to present registers @samp{ev0} through @samp{ev31} to the
user.
+The @samp{org.gnu.gdb.power.dfp128} feature is optional and i aimed at Targets
+that support DFP types. It should contain registers @samp{dl0} through
+@samp{dl15}. Each @samp{dl} register is actually a pair of 64-bit Floating
+Point registers, so, for example, @samp{dl0} is composed by joining @samp{f0}
+and @samp{f1}. @value{GDBN} will combined the pair of Floating
+Point registers to present a single @samp{dl} register.
+
@include gpl.texi
@raisesections
Index: git/gdb/testsuite/gdb.arch/powerpc-d128-regs.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ git/gdb/testsuite/gdb.arch/powerpc-d128-regs.c 2007-11-06 09:41:24.000000000 -0800
@@ -0,0 +1,25 @@
+/* This file is part of GDB, the GNU debugger.
+
+ Copyright 2007 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 the PPC64 Decimal128 pseudo-registers. */
+
+int main(void)
+{
+ _Decimal128 d128 = 1.2345678910dl;
+
+ return 0;
+}
Index: git/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ git/gdb/testsuite/gdb.arch/powerpc-d128-regs.exp 2007-11-06 10:04:57.000000000 -0800
@@ -0,0 +1,77 @@
+# This testcase is part of GDB, the GNU debugger.
+
+# Copyright 2007
+# 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 the PPC64 Decimal128 pseudo-registers.
+
+if $tracelevel then {
+ strace $tracelevel
+}
+
+if ![istarget "powerpc64-*"] then {
+ verbose "Skipping powerpc64 Decimal128 pseudo-registers testcase."
+ return
+}
+
+set testfile "powerpc64-d128-regs"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+
+if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {quiet debug}] != "" } {
+ untested printcmds.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:common64.*" "Checking for PPC64 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\[ \]*0x2205800000000000000000049c5de09c\[\t\]*1\.2345678910" \
+ "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"
+
+}
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: [PATCH] PPC - Printing Decimal 128 types out of registers
2007-11-07 19:33 [PATCH] PPC - Printing Decimal 128 types out of registers Luis Machado
@ 2007-11-26 21:40 ` Luis Machado
2007-12-26 12:42 ` [PING] " Luis Machado
2008-01-17 19:03 ` Printing decimal128 " Luis Machado
1 sibling, 1 reply; 31+ messages in thread
From: Luis Machado @ 2007-11-26 21:40 UTC (permalink / raw)
To: gdb-patches
Hi there,
Did anyone have a chance to go through this one?
Regards,
Luis
On Wed, 2007-11-07 at 16:33 -0200, Luis Machado wrote:
> Hi folks,
>
> I'm continuing the work to enhance DFP type support on GDB. DFP types
> are nativelly supported on the Power6 processor, thus they are stored in
> registers as so. This patch handles the printing and setting of
> Decimal128 types directly out of/in the registers.
>
> A Decimal128 type is stored using pairs of Floating Point registers, and
> it always starts in an even-numbered register. So, we could, for
> example, have a Decimal128 var taking up FPR0-FPR1, FPR10-FPR11, but
> never FPR1-FPR2 or FPR23-24.
>
> Right now GDB isn't able to print those vars as it doesn't know they
> take up more than one register.
>
> The idea to overcome this was to create a new set of 16 Decimal128-typed
> pseudo-registers called DL (Standing for "D"ecimal "L"ong Double) that
> would represent all 16 pairs of Floating Point Registers.. By using a
> pseudo-register mechanism, we're able to force the DL/FPR registers to
> map directly into the FPR/DL registers.
>
> Benefits of this change include:
>
> * Better printing support for Decimal128 types. We just print the
> register as is. No need to include casting tricks and arrays to print
> that value.
>
> * Straightforward way of setting Decimal128 values directly in the
> registers. We just "set $dl0=1.23dl", for example, and it's
> automatically set.
>
> * Overview of the state of 16 Decimal128 registers using the "info reg
> all" command.
>
>
> Supporting the patch there is also a number of other modifications, as
> listed:
>
> * DFP types are now global since they were included as predefined types
> in the "target-descriptions.c" file.
>
> * A simple testcase making sure the registers are working as expected.
>
> * Piece of documentation for the GDB manual.
>
> * Fix to display a 128-bit hex literal representation of Decimal128
> types (using "info reg").
>
> Also note that this support will be available for both ppc64 and ppc32.
>
> Looking forward to have comments and suggestions for improvements.
>
> Regards,
> Luis
--
Luis Machado
IBM Linux Technology Center
e-mail: luisgpm@linux.vnet.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* [PING] PPC - Printing Decimal 128 types out of registers
2007-11-26 21:40 ` Luis Machado
@ 2007-12-26 12:42 ` Luis Machado
0 siblings, 0 replies; 31+ messages in thread
From: Luis Machado @ 2007-12-26 12:42 UTC (permalink / raw)
To: gdb-patches
Hi,
I'm looking forward to refresh this patch, would anyone have comments on
it? It's been a while since i first submitted this one.
Best regards,
On Mon, 2007-11-26 at 19:40 -0200, Luis Machado wrote:
> Hi there,
>
> Did anyone have a chance to go through this one?
>
> Regards,
> Luis
>
> On Wed, 2007-11-07 at 16:33 -0200, Luis Machado wrote:
> > Hi folks,
> >
> > I'm continuing the work to enhance DFP type support on GDB. DFP types
> > are nativelly supported on the Power6 processor, thus they are stored in
> > registers as so. This patch handles the printing and setting of
> > Decimal128 types directly out of/in the registers.
> >
> > A Decimal128 type is stored using pairs of Floating Point registers, and
> > it always starts in an even-numbered register. So, we could, for
> > example, have a Decimal128 var taking up FPR0-FPR1, FPR10-FPR11, but
> > never FPR1-FPR2 or FPR23-24.
> >
> > Right now GDB isn't able to print those vars as it doesn't know they
> > take up more than one register.
> >
> > The idea to overcome this was to create a new set of 16 Decimal128-typed
> > pseudo-registers called DL (Standing for "D"ecimal "L"ong Double) that
> > would represent all 16 pairs of Floating Point Registers.. By using a
> > pseudo-register mechanism, we're able to force the DL/FPR registers to
> > map directly into the FPR/DL registers.
> >
> > Benefits of this change include:
> >
> > * Better printing support for Decimal128 types. We just print the
> > register as is. No need to include casting tricks and arrays to print
> > that value.
> >
> > * Straightforward way of setting Decimal128 values directly in the
> > registers. We just "set $dl0=1.23dl", for example, and it's
> > automatically set.
> >
> > * Overview of the state of 16 Decimal128 registers using the "info reg
> > all" command.
> >
> >
> > Supporting the patch there is also a number of other modifications, as
> > listed:
> >
> > * DFP types are now global since they were included as predefined types
> > in the "target-descriptions.c" file.
> >
> > * A simple testcase making sure the registers are working as expected.
> >
> > * Piece of documentation for the GDB manual.
> >
> > * Fix to display a 128-bit hex literal representation of Decimal128
> > types (using "info reg").
> >
> > Also note that this support will be available for both ppc64 and ppc32.
> >
> > Looking forward to have comments and suggestions for improvements.
> >
> > Regards,
> > Luis
--
Luis Machado
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2007-11-07 19:33 [PATCH] PPC - Printing Decimal 128 types out of registers Luis Machado
2007-11-26 21:40 ` Luis Machado
@ 2008-01-17 19:03 ` Luis Machado
2008-01-17 19:36 ` Thiago Jung Bauermann
1 sibling, 1 reply; 31+ messages in thread
From: Luis Machado @ 2008-01-17 19:03 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 2455 bytes --]
Hi,
The patch to handle DFP expressions had some overlapping with this
patch, and since this was a bit old already, follows a refreshed version
for HEAD.
The patch remains essentially the same, with a few fixes. Running the
testsuite showed no regressions on 32-bit/64-bit ppc.
Is this OK to go in?
Regards,
Luis
On Wed, 2007-11-07 at 16:33 -0200, Luis Machado wrote:
> Hi folks,
>
> I'm continuing the work to enhance DFP type support on GDB. DFP types
> are nativelly supported on the Power6 processor, thus they are stored in
> registers as so. This patch handles the printing and setting of
> Decimal128 types directly out of/in the registers.
>
> A Decimal128 type is stored using pairs of Floating Point registers, and
> it always starts in an even-numbered register. So, we could, for
> example, have a Decimal128 var taking up FPR0-FPR1, FPR10-FPR11, but
> never FPR1-FPR2 or FPR23-24.
>
> Right now GDB isn't able to print those vars as it doesn't know they
> take up more than one register.
>
> The idea to overcome this was to create a new set of 16 Decimal128-typed
> pseudo-registers called DL (Standing for "D"ecimal "L"ong Double) that
> would represent all 16 pairs of Floating Point Registers.. By using a
> pseudo-register mechanism, we're able to force the DL/FPR registers to
> map directly into the FPR/DL registers.
>
> Benefits of this change include:
>
> * Better printing support for Decimal128 types. We just print the
> register as is. No need to include casting tricks and arrays to print
> that value.
>
> * Straightforward way of setting Decimal128 values directly in the
> registers. We just "set $dl0=1.23dl", for example, and it's
> automatically set.
>
> * Overview of the state of 16 Decimal128 registers using the "info reg
> all" command.
>
>
> Supporting the patch there is also a number of other modifications, as
> listed:
>
> * DFP types are now global since they were included as predefined types
> in the "target-descriptions.c" file.
>
> * A simple testcase making sure the registers are working as expected.
>
> * Piece of documentation for the GDB manual.
>
> * Fix to display a 128-bit hex literal representation of Decimal128
> types (using "info reg").
>
> Also note that this support will be available for both ppc64 and ppc32.
>
> Looking forward to have comments and suggestions for improvements.
>
> Regards,
> Luis
--
Luis Machado
Software Engineer
IBM Linux Technology Center
[-- Attachment #2: registers-dfp.diff --]
[-- Type: text/x-patch, Size: 15947 bytes --]
2008-01-17 Luis Machado <luisgpm@br.ibm.com>
* rs6000-tdep.c (rs6000_gdbarch_init): Add support for
Decimal128 pseudo-registers.
(rs6000_pseudo_register_type): Returns the correct type for
Decimal128 pseudo-registers.
(rs6000_pseudo_register_reggroup_p): Returns the correct register
group for Decimal128 pseudo-registers.
(ppc_pseudo_register_read): New function.
(ppc_pseudo_register_write): New function.
* ppc-tdep.h: Add new variables ppc_dl0_upper_regnum, ppc_dl0_regnum
and ppc_dl15_regnum.
* printcmd.c: Fix displaying of DFP types as hex.
* features/rs6000/powerpc-64.c (initialize_tdesc_powerpc_64): Create
a new feature for Decimal128 pseudo-registers.
* features/rs6000/powerpc-32.c (initialize_tdesc_powerpc_32): Create
a new feature for Decimal128 pseudo-registers.
* testsuite/gdb.arch/powerpc-d128-regs.exp: New testcase expect
file.
* testsuite/gdb.arch/powerpc-d128-regs.c: New testcase source
file.
* doc/gdb.textinfo: Add new powerpc dfp128 feature documentation.
Index: gdb/rs6000-tdep.c
===================================================================
--- gdb.orig/rs6000-tdep.c 2008-01-17 10:43:31.000000000 -0800
+++ gdb/rs6000-tdep.c 2008-01-17 10:44:39.000000000 -0800
@@ -2384,6 +2384,20 @@
return spe_regnames[regno - tdep->ppc_ev0_regnum];
}
+ /* Check if the decimal128 pseudo-registers are available. */
+ if (tdep->ppc_dl0_regnum >= 0
+ && tdep->ppc_dl0_regnum <= regno
+ && regno < tdep->ppc_dl0_regnum + 16)
+ {
+ 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);
}
@@ -2395,12 +2409,19 @@
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- /* These are the only pseudo-registers we support. */
- gdb_assert (tdep->ppc_ev0_regnum >= 0
- && regnum >= tdep->ppc_ev0_regnum
- && regnum < tdep->ppc_ev0_regnum + 32);
+ /* These are the e500 pseudo-registers. */
+ if (tdep->ppc_ev0_regnum >= 0
+ && regnum >= tdep->ppc_ev0_regnum
+ && regnum < tdep->ppc_ev0_regnum + 32)
+ return rs6000_builtin_type_vec64 (gdbarch);
+
+ /* These are the ppc decimal128 pseudo-registers. */
+ if (tdep->ppc_dl0_regnum >= 0
+ && regnum >= tdep->ppc_dl0_regnum
+ && regnum < tdep->ppc_dl0_regnum + 16)
+ return builtin_type (current_gdbarch)->builtin_declong;;
- return rs6000_builtin_type_vec64 (gdbarch);
+ return NULL;
}
/* Is REGNUM a member of REGGROUP? */
@@ -2410,10 +2431,17 @@
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- /* These are the only pseudo-registers we support. */
- gdb_assert (tdep->ppc_ev0_regnum >= 0
- && regnum >= tdep->ppc_ev0_regnum
- && regnum < tdep->ppc_ev0_regnum + 32);
+ /* These are the e500 pseudo-registers. */
+ if (tdep->ppc_ev0_regnum < 0
+ && regnum < tdep->ppc_ev0_regnum
+ && regnum >= tdep->ppc_ev0_regnum + 32)
+ return -1;
+
+ /* These are the ppc decimal128 pseudo-registers. */
+ if (tdep->ppc_dl0_regnum < 0
+ && regnum < tdep->ppc_dl0_regnum
+ && regnum >= tdep->ppc_dl0_regnum + 16)
+ return -1;
if (group == all_reggroup || group == vector_reggroup)
return 1;
@@ -2556,6 +2584,89 @@
gdbarch_register_name (gdbarch, reg_nr), reg_nr);
}
+/* 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 *regcache_arch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int reg_index;
+ gdb_byte *byte_buffer = buffer;
+
+ gdb_assert (regcache_arch == gdbarch);
+
+ if (tdep->ppc_dl0_regnum <= reg_nr
+ && reg_nr < tdep->ppc_dl0_regnum + 16)
+ {
+ 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, byte_buffer);
+ regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, byte_buffer + 8);
+ }
+ else
+ {
+ regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, byte_buffer + 8);
+ regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index, byte_buffer);
+ }
+ }
+ else
+ internal_error (__FILE__, __LINE__,
+ _("ppc_pseudo_register_read: "
+ "called on unexpected register '%s' (%d)"),
+ gdbarch_register_name (gdbarch, reg_nr), reg_nr);
+}
+
+/* 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 *regcache_arch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int reg_index;
+ const gdb_byte *byte_buffer = buffer;
+
+ gdb_assert (regcache_arch == gdbarch);
+
+ if (tdep->ppc_dl0_regnum <= reg_nr
+ && reg_nr < tdep->ppc_dl0_regnum + 16)
+ {
+ 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, byte_buffer);
+ regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, byte_buffer + 8);
+ }
+ else
+ {
+ regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, byte_buffer + 8);
+ regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index, byte_buffer);
+ }
+ }
+ else
+ internal_error (__FILE__, __LINE__,
+ _("ppc_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. */
static int
rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
@@ -3174,7 +3285,8 @@
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_dfp128 = 0;
int tdesc_wordsize = -1;
const struct target_desc *tdesc = info.target_desc;
struct tdesc_arch_data *tdesc_data = NULL;
@@ -3380,6 +3492,12 @@
else
have_altivec = 0;
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.dfp128");
+
+ if (feature != NULL)
+ have_dfp128 = 1;
+
/* On machines supporting the SPE APU, the general-purpose registers
are 64 bits long. There are SIMD vector instructions to treat them
as pairs of floats, but the rest of the instruction set treats them
@@ -3568,6 +3686,7 @@
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_dfp128 ? PPC_F0_REGNUM : -1;
set_gdbarch_pc_regnum (gdbarch, PPC_PC_REGNUM);
set_gdbarch_sp_regnum (gdbarch, PPC_R0_REGNUM + 1);
@@ -3600,6 +3719,12 @@
set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write);
}
+ else
+ if (have_dfp128)
+ {
+ set_gdbarch_pseudo_register_read (gdbarch, ppc_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch, ppc_pseudo_register_write);
+ }
set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
@@ -3610,7 +3735,12 @@
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)
+ set_gdbarch_num_pseudo_regs (gdbarch, 32);
+ else
+ if (have_dfp128)
+ set_gdbarch_num_pseudo_regs (gdbarch, 16);
set_gdbarch_ptr_bit (gdbarch, wordsize * TARGET_CHAR_BIT);
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
@@ -3734,6 +3864,10 @@
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_dfp128 ? gdbarch_num_regs (gdbarch) : -1;
+ tdep->ppc_dl15_regnum = have_dfp128 ? tdep->ppc_dl0_regnum + 15 : -1;
+
return gdbarch;
}
Index: gdb/ppc-tdep.h
===================================================================
--- gdb.orig/ppc-tdep.h 2008-01-17 10:43:31.000000000 -0800
+++ gdb/ppc-tdep.h 2008-01-17 10:43:51.000000000 -0800
@@ -205,6 +205,11 @@
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;
Index: gdb/features/rs6000/powerpc-64.c
===================================================================
--- gdb.orig/features/rs6000/powerpc-64.c 2008-01-17 10:43:31.000000000 -0800
+++ gdb/features/rs6000/powerpc-64.c 2008-01-17 10:43:51.000000000 -0800
@@ -160,5 +160,7 @@
tdesc_create_reg (feature, "vscr", 103, 1, "vector", 32, "int");
tdesc_create_reg (feature, "vrsave", 104, 1, "vector", 32, "int");
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.dfp128");
+
tdesc_powerpc_64 = result;
}
Index: gdb/features/rs6000/powerpc-32.c
===================================================================
--- gdb.orig/features/rs6000/powerpc-32.c 2008-01-17 10:43:31.000000000 -0800
+++ gdb/features/rs6000/powerpc-32.c 2008-01-17 10:43:51.000000000 -0800
@@ -160,5 +160,7 @@
tdesc_create_reg (feature, "vscr", 103, 1, "vector", 32, "int");
tdesc_create_reg (feature, "vrsave", 104, 1, "vector", 32, "int");
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.dfp128");
+
tdesc_powerpc_32 = result;
}
Index: gdb/doc/gdb.texinfo
===================================================================
--- gdb.orig/doc/gdb.texinfo 2008-01-17 10:43:31.000000000 -0800
+++ gdb/doc/gdb.texinfo 2008-01-17 10:43:51.000000000 -0800
@@ -26654,6 +26654,13 @@
these to present registers @samp{ev0} through @samp{ev31} to the
user.
+The @samp{org.gnu.gdb.power.dfp128} feature is optional and is aimed at targets
+that support DFP types. It should contain registers @samp{dl0} through
+@samp{dl15}. Each @samp{dl} register is actually a pair of 64-bit floating
+point registers, so, for example, @samp{dl0} is composed by joining @samp{f0}
+and @samp{f1}. @value{GDBN} will combine the pair of floating
+point registers to present a single @samp{dl} register.
+
@include gpl.texi
@raisesections
Index: gdb/testsuite/gdb.arch/powerpc-d128-regs.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.arch/powerpc-d128-regs.c 2008-01-17 10:43:51.000000000 -0800
@@ -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;
+}
Index: gdb/testsuite/gdb.arch/powerpc-d128-regs.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.arch/powerpc-d128-regs.exp 2008-01-17 10:43:51.000000000 -0800
@@ -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\[ \]*0x2205800000000000000000049c5de09c\[\t\]*1\.2345678910" \
+ "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: gdb/printcmd.c
===================================================================
--- gdb.orig/printcmd.c 2008-01-17 10:48:18.000000000 -0800
+++ gdb/printcmd.c 2008-01-17 10:48:29.000000000 -0800
@@ -326,7 +326,8 @@
if (len > sizeof(LONGEST) &&
(TYPE_CODE (type) == TYPE_CODE_INT
- || TYPE_CODE (type) == TYPE_CODE_ENUM))
+ || TYPE_CODE (type) == TYPE_CODE_ENUM
+ || TYPE_CODE (type) == TYPE_CODE_DECFLOAT))
{
switch (format)
{
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Printing decimal128 types out of registers
2008-01-17 19:03 ` Printing decimal128 " Luis Machado
@ 2008-01-17 19:36 ` Thiago Jung Bauermann
2008-01-18 15:43 ` Luis Machado
2008-01-21 17:54 ` Daniel Jacobowitz
0 siblings, 2 replies; 31+ messages in thread
From: Thiago Jung Bauermann @ 2008-01-17 19:36 UTC (permalink / raw)
To: luisgpm; +Cc: gdb-patches
On Thu, 2008-01-17 at 17:03 -0200, Luis Machado wrote:
> Hi,
>
> The patch to handle DFP expressions had some overlapping with this
> patch, and since this was a bit old already, follows a refreshed version
> for HEAD.
>
> The patch remains essentially the same, with a few fixes. Running the
> testsuite showed no regressions on 32-bit/64-bit ppc.
>
> Is this OK to go in?
A few comments, mostly formatting:
> + /* These are the e500 pseudo-registers. */
> + if (tdep->ppc_ev0_regnum >= 0
> + && regnum >= tdep->ppc_ev0_regnum
> + && regnum < tdep->ppc_ev0_regnum + 32)
> + return rs6000_builtin_type_vec64 (gdbarch);
> +
> + /* These are the ppc decimal128 pseudo-registers. */
> + if (tdep->ppc_dl0_regnum >= 0
> + && regnum >= tdep->ppc_dl0_regnum
> + && regnum < tdep->ppc_dl0_regnum + 16)
> + return builtin_type (current_gdbarch)->builtin_declong;;
>
> + /* These are the e500 pseudo-registers. */
> + if (tdep->ppc_ev0_regnum < 0
> + && regnum < tdep->ppc_ev0_regnum
> + && regnum >= tdep->ppc_ev0_regnum + 32)
> + return -1;
> +
> + /* These are the ppc decimal128 pseudo-registers. */
> + if (tdep->ppc_dl0_regnum < 0
> + && regnum < tdep->ppc_dl0_regnum
> + && regnum >= tdep->ppc_dl0_regnum + 16)
> + return -1;
The return statements above are too indented.
> - 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_dfp128 = 0;
have_dfp128 shouldn't be aligned with int. Not sure which column it
should be though.
> + else
> + if (have_dfp128)
> + {
> + set_gdbarch_pseudo_register_read (gdbarch,
ppc_pseudo_register_read);
> + set_gdbarch_pseudo_register_write (gdbarch,
ppc_pseudo_register_write);
> + }
>
> +
> + if (have_spe)
> + set_gdbarch_num_pseudo_regs (gdbarch, 32);
> + else
> + if (have_dfp128)
> + set_gdbarch_num_pseudo_regs (gdbarch, 16);
IMHO, "else" should be immediately followed by if, not put in a
separate line.
> Index: gdb/features/rs6000/powerpc-64.c
> [...]
> Index: gdb/features/rs6000/powerpc-32.c
These files are generated. You should edit the XML and regenerate.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Printing decimal128 types out of registers
2008-01-17 19:36 ` Thiago Jung Bauermann
@ 2008-01-18 15:43 ` Luis Machado
2008-01-18 16:12 ` Mark Kettenis
2008-01-19 0:04 ` Daniel Jacobowitz
2008-01-21 17:54 ` Daniel Jacobowitz
1 sibling, 2 replies; 31+ messages in thread
From: Luis Machado @ 2008-01-18 15:43 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 225 bytes --]
> These files are generated. You should edit the XML and regenerate.
Fixed the formatting issues and regenerated the c files based on the xml
files.
Regards,
--
Luis Machado
Software Engineer
IBM Linux Technology Center
[-- Attachment #2: registers-dfp.diff --]
[-- Type: text/x-patch, Size: 17514 bytes --]
2008-01-18 Luis Machado <luisgpm@br.ibm.com>
* rs6000-tdep.c (rs6000_gdbarch_init): Add support for
Decimal128 pseudo-registers.
(rs6000_pseudo_register_type): Returns the correct type for
Decimal128 pseudo-registers.
(rs6000_pseudo_register_reggroup_p): Returns the correct register
group for Decimal128 pseudo-registers.
(ppc_pseudo_register_read): New function.
(ppc_pseudo_register_write): New function.
* ppc-tdep.h: Add new variables ppc_dl0_upper_regnum, ppc_dl0_regnum
and ppc_dl15_regnum.
* printcmd.c: Fix displaying of DFP types as hex.
* features/rs6000/powerpc-64.c: Regenerate.
* features/rs6000/powerpc-32.c: Regenerate.
* features/rs6000/powerpc-64.xml: Add decimal128 feature.
* features/rs6000/powerpc-32.xml: Add decimal128 feature.
* features/rs6000/power-dfp128.xml: New file.
* testsuite/gdb.arch/powerpc-d128-regs.exp: New testcase expect
file.
* testsuite/gdb.arch/powerpc-d128-regs.c: New testcase source
file.
* doc/gdb.textinfo: Add new powerpc dfp128 feature documentation.
Index: gdb/rs6000-tdep.c
===================================================================
--- gdb.orig/rs6000-tdep.c 2008-01-18 05:15:36.000000000 -0800
+++ gdb/rs6000-tdep.c 2008-01-18 05:15:57.000000000 -0800
@@ -2384,6 +2384,20 @@
return spe_regnames[regno - tdep->ppc_ev0_regnum];
}
+ /* Check if the decimal128 pseudo-registers are available. */
+ if (tdep->ppc_dl0_regnum >= 0
+ && tdep->ppc_dl0_regnum <= regno
+ && regno < tdep->ppc_dl0_regnum + 16)
+ {
+ 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);
}
@@ -2395,12 +2409,19 @@
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- /* These are the only pseudo-registers we support. */
- gdb_assert (tdep->ppc_ev0_regnum >= 0
- && regnum >= tdep->ppc_ev0_regnum
- && regnum < tdep->ppc_ev0_regnum + 32);
+ /* These are the e500 pseudo-registers. */
+ if (tdep->ppc_ev0_regnum >= 0
+ && regnum >= tdep->ppc_ev0_regnum
+ && regnum < tdep->ppc_ev0_regnum + 32)
+ return rs6000_builtin_type_vec64 (gdbarch);
+
+ /* These are the ppc decimal128 pseudo-registers. */
+ if (tdep->ppc_dl0_regnum >= 0
+ && regnum >= tdep->ppc_dl0_regnum
+ && regnum < tdep->ppc_dl0_regnum + 16)
+ return builtin_type (current_gdbarch)->builtin_declong;;
- return rs6000_builtin_type_vec64 (gdbarch);
+ return NULL;
}
/* Is REGNUM a member of REGGROUP? */
@@ -2410,10 +2431,17 @@
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- /* These are the only pseudo-registers we support. */
- gdb_assert (tdep->ppc_ev0_regnum >= 0
- && regnum >= tdep->ppc_ev0_regnum
- && regnum < tdep->ppc_ev0_regnum + 32);
+ /* These are the e500 pseudo-registers. */
+ if (tdep->ppc_ev0_regnum < 0
+ && regnum < tdep->ppc_ev0_regnum
+ && regnum >= tdep->ppc_ev0_regnum + 32)
+ return -1;
+
+ /* These are the ppc decimal128 pseudo-registers. */
+ if (tdep->ppc_dl0_regnum < 0
+ && regnum < tdep->ppc_dl0_regnum
+ && regnum >= tdep->ppc_dl0_regnum + 16)
+ return -1;
if (group == all_reggroup || group == vector_reggroup)
return 1;
@@ -2556,6 +2584,89 @@
gdbarch_register_name (gdbarch, reg_nr), reg_nr);
}
+/* 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 *regcache_arch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int reg_index;
+ gdb_byte *byte_buffer = buffer;
+
+ gdb_assert (regcache_arch == gdbarch);
+
+ if (tdep->ppc_dl0_regnum <= reg_nr
+ && reg_nr < tdep->ppc_dl0_regnum + 16)
+ {
+ 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, byte_buffer);
+ regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, byte_buffer + 8);
+ }
+ else
+ {
+ regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, byte_buffer + 8);
+ regcache_raw_read (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index, byte_buffer);
+ }
+ }
+ else
+ internal_error (__FILE__, __LINE__,
+ _("ppc_pseudo_register_read: "
+ "called on unexpected register '%s' (%d)"),
+ gdbarch_register_name (gdbarch, reg_nr), reg_nr);
+}
+
+/* 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 *regcache_arch = get_regcache_arch (regcache);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int reg_index;
+ const gdb_byte *byte_buffer = buffer;
+
+ gdb_assert (regcache_arch == gdbarch);
+
+ if (tdep->ppc_dl0_regnum <= reg_nr
+ && reg_nr < tdep->ppc_dl0_regnum + 16)
+ {
+ 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, byte_buffer);
+ regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, byte_buffer + 8);
+ }
+ else
+ {
+ regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index + 1, byte_buffer + 8);
+ regcache_raw_write (regcache, tdep->ppc_dl0_upper_regnum +
+ 2 * reg_index, byte_buffer);
+ }
+ }
+ else
+ internal_error (__FILE__, __LINE__,
+ _("ppc_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. */
static int
rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
@@ -3174,7 +3285,8 @@
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_dfp128 = 0;
int tdesc_wordsize = -1;
const struct target_desc *tdesc = info.target_desc;
struct tdesc_arch_data *tdesc_data = NULL;
@@ -3380,6 +3492,12 @@
else
have_altivec = 0;
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.dfp128");
+
+ if (feature != NULL)
+ have_dfp128 = 1;
+
/* On machines supporting the SPE APU, the general-purpose registers
are 64 bits long. There are SIMD vector instructions to treat them
as pairs of floats, but the rest of the instruction set treats them
@@ -3568,6 +3686,7 @@
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_dfp128 ? PPC_F0_REGNUM : -1;
set_gdbarch_pc_regnum (gdbarch, PPC_PC_REGNUM);
set_gdbarch_sp_regnum (gdbarch, PPC_R0_REGNUM + 1);
@@ -3600,6 +3719,11 @@
set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write);
}
+ else if (have_dfp128)
+ {
+ set_gdbarch_pseudo_register_read (gdbarch, ppc_pseudo_register_read);
+ set_gdbarch_pseudo_register_write (gdbarch, ppc_pseudo_register_write);
+ }
set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
@@ -3610,7 +3734,12 @@
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)
+ set_gdbarch_num_pseudo_regs (gdbarch, 32);
+ else
+ if (have_dfp128)
+ set_gdbarch_num_pseudo_regs (gdbarch, 16);
set_gdbarch_ptr_bit (gdbarch, wordsize * TARGET_CHAR_BIT);
set_gdbarch_short_bit (gdbarch, 2 * TARGET_CHAR_BIT);
@@ -3734,6 +3863,10 @@
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_dfp128 ? gdbarch_num_regs (gdbarch) : -1;
+ tdep->ppc_dl15_regnum = have_dfp128 ? tdep->ppc_dl0_regnum + 15 : -1;
+
return gdbarch;
}
Index: gdb/ppc-tdep.h
===================================================================
--- gdb.orig/ppc-tdep.h 2008-01-18 05:15:36.000000000 -0800
+++ gdb/ppc-tdep.h 2008-01-18 05:15:57.000000000 -0800
@@ -205,6 +205,11 @@
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;
Index: gdb/features/rs6000/powerpc-64.c
===================================================================
--- gdb.orig/features/rs6000/powerpc-64.c 2008-01-18 05:15:36.000000000 -0800
+++ gdb/features/rs6000/powerpc-64.c 2008-01-18 07:29:24.000000000 -0800
@@ -160,5 +160,7 @@
tdesc_create_reg (feature, "vscr", 103, 1, "vector", 32, "int");
tdesc_create_reg (feature, "vrsave", 104, 1, "vector", 32, "int");
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.dfp128");
+
tdesc_powerpc_64 = result;
}
Index: gdb/features/rs6000/powerpc-32.c
===================================================================
--- gdb.orig/features/rs6000/powerpc-32.c 2008-01-18 05:15:36.000000000 -0800
+++ gdb/features/rs6000/powerpc-32.c 2008-01-18 05:15:57.000000000 -0800
@@ -160,5 +160,7 @@
tdesc_create_reg (feature, "vscr", 103, 1, "vector", 32, "int");
tdesc_create_reg (feature, "vrsave", 104, 1, "vector", 32, "int");
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.dfp128");
+
tdesc_powerpc_32 = result;
}
Index: gdb/doc/gdb.texinfo
===================================================================
--- gdb.orig/doc/gdb.texinfo 2008-01-18 05:15:36.000000000 -0800
+++ gdb/doc/gdb.texinfo 2008-01-18 05:15:57.000000000 -0800
@@ -26654,6 +26654,13 @@
these to present registers @samp{ev0} through @samp{ev31} to the
user.
+The @samp{org.gnu.gdb.power.dfp128} feature is optional and is aimed at targets
+that support DFP types. It should contain registers @samp{dl0} through
+@samp{dl15}. Each @samp{dl} register is actually a pair of 64-bit floating
+point registers, so, for example, @samp{dl0} is composed by joining @samp{f0}
+and @samp{f1}. @value{GDBN} will combine the pair of floating
+point registers to present a single @samp{dl} register.
+
@include gpl.texi
@raisesections
Index: gdb/testsuite/gdb.arch/powerpc-d128-regs.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.arch/powerpc-d128-regs.c 2008-01-18 05:15:57.000000000 -0800
@@ -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;
+}
Index: gdb/testsuite/gdb.arch/powerpc-d128-regs.exp
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb/testsuite/gdb.arch/powerpc-d128-regs.exp 2008-01-18 05:15:57.000000000 -0800
@@ -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\[ \]*0x2205800000000000000000049c5de09c\[\t\]*1\.2345678910" \
+ "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: gdb/printcmd.c
===================================================================
--- gdb.orig/printcmd.c 2008-01-18 05:15:36.000000000 -0800
+++ gdb/printcmd.c 2008-01-18 05:15:57.000000000 -0800
@@ -326,7 +326,8 @@
if (len > sizeof(LONGEST) &&
(TYPE_CODE (type) == TYPE_CODE_INT
- || TYPE_CODE (type) == TYPE_CODE_ENUM))
+ || TYPE_CODE (type) == TYPE_CODE_ENUM
+ || TYPE_CODE (type) == TYPE_CODE_DECFLOAT))
{
switch (format)
{
Index: gdb/features/rs6000/powerpc-32.xml
===================================================================
--- gdb.orig/features/rs6000/powerpc-32.xml 2008-01-18 05:15:36.000000000 -0800
+++ gdb/features/rs6000/powerpc-32.xml 2008-01-18 05:15:57.000000000 -0800
@@ -14,4 +14,5 @@
<xi:include href="power-core.xml"/>
<xi:include href="power-fpu.xml"/>
<xi:include href="power-altivec.xml"/>
+ <xi:include href="power-dfp128.xml"/>
</target>
Index: gdb/features/rs6000/powerpc-64.xml
===================================================================
--- gdb.orig/features/rs6000/powerpc-64.xml 2008-01-18 05:15:36.000000000 -0800
+++ gdb/features/rs6000/powerpc-64.xml 2008-01-18 05:15:57.000000000 -0800
@@ -14,4 +14,5 @@
<xi:include href="power64-core.xml"/>
<xi:include href="power-fpu.xml"/>
<xi:include href="power-altivec.xml"/>
+ <xi:include href="power-dfp128.xml"/>
</target>
Index: gdb/features/rs6000/power-dfp128.xml
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ gdb/features/rs6000/power-dfp128.xml 2008-01-18 05:15:36.000000000 -0800
@@ -0,0 +1,9 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2007, 2008 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.power.dfp128"></feature>
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Printing decimal128 types out of registers
2008-01-18 15:43 ` Luis Machado
@ 2008-01-18 16:12 ` Mark Kettenis
2008-01-18 16:38 ` Luis Machado
2008-01-19 0:04 ` Daniel Jacobowitz
1 sibling, 1 reply; 31+ messages in thread
From: Mark Kettenis @ 2008-01-18 16:12 UTC (permalink / raw)
To: luisgpm; +Cc: bauerman, gdb-patches
> From: Luis Machado <luisgpm@linux.vnet.ibm.com>
> Date: Fri, 18 Jan 2008 13:42:34 -0200
>
> > These files are generated. You should edit the XML and regenerate.
>
> Fixed the formatting issues and regenerated the c files based on the xml
> files.
Sorry for not noticing earlier, but why do we need target description
feature for *pseudo* registers?
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2008-01-18 16:12 ` Mark Kettenis
@ 2008-01-18 16:38 ` Luis Machado
2008-01-18 17:20 ` Mark Kettenis
0 siblings, 1 reply; 31+ messages in thread
From: Luis Machado @ 2008-01-18 16:38 UTC (permalink / raw)
To: Mark Kettenis; +Cc: bauerman, gdb-patches
> Sorry for not noticing earlier, but why do we need target description
> feature for *pseudo* registers?
>
The purpose of this feature in the target description is to tell GDB
which targets support these pseudo-registers, so we're sure that they
won't appear on other ppc32 targets that do not support it.
This seemed to be a more natural way of doing this, instead of filling
the code with target-related conditionals.
Regards,
--
Luis Machado
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2008-01-18 16:38 ` Luis Machado
@ 2008-01-18 17:20 ` Mark Kettenis
2008-01-18 18:52 ` Luis Machado
0 siblings, 1 reply; 31+ messages in thread
From: Mark Kettenis @ 2008-01-18 17:20 UTC (permalink / raw)
To: luisgpm; +Cc: bauerman, gdb-patches
> From: Luis Machado <luisgpm@linux.vnet.ibm.com>
> Date: Fri, 18 Jan 2008 14:38:02 -0200
>
> > Sorry for not noticing earlier, but why do we need target description
> > feature for *pseudo* registers?
> >
>
> The purpose of this feature in the target description is to tell GDB
> which targets support these pseudo-registers, so we're sure that they
> won't appear on other ppc32 targets that do not support it.
But they're pseudo-registers; no target "supports" them because
they're not real registers. Are you trying to say that some targets
have hardware support for decimal floating point, and you want to make
sure that these pseudo registers only show up on targets that have
such hardware support? If so I'd appreciate it if you could change
the comments to reflect that.
There are no software implementations that use the floating-point
registers in the same way as the hardware implementation does?
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2008-01-18 17:20 ` Mark Kettenis
@ 2008-01-18 18:52 ` Luis Machado
2008-01-18 19:54 ` Mark Kettenis
0 siblings, 1 reply; 31+ messages in thread
From: Luis Machado @ 2008-01-18 18:52 UTC (permalink / raw)
To: Mark Kettenis; +Cc: bauerman, gdb-patches
> But they're pseudo-registers; no target "supports" them because
> they're not real registers. Are you trying to say that some targets
> have hardware support for decimal floating point, and you want to make
> sure that these pseudo registers only show up on targets that have
> such hardware support? If so I'd appreciate it if you could change
> the comments to reflect that.
The idea is to have a "decimal128" feature meaning that we're supposed
to show these pseudo-registers for ppc32 and ppc64, similar to the way
the EV registers work on the e500, except that we have (in the e500) 32
of those being real registers and the other 32 being pseudo-registers.
All those 64 registers sum up to create a single set of 32 64-bit
registers (power-spe feature).
> There are no software implementations that use the floating-point
> registers in the same way as the hardware implementation does?
Yes, there is. This would work the same way with software
implementations, that is, we would have the same parameter passing
scheme using pairs of FP registers.
--
Luis Machado
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2008-01-18 18:52 ` Luis Machado
@ 2008-01-18 19:54 ` Mark Kettenis
0 siblings, 0 replies; 31+ messages in thread
From: Mark Kettenis @ 2008-01-18 19:54 UTC (permalink / raw)
To: luisgpm; +Cc: bauerman, gdb-patches
> From: Luis Machado <luisgpm@linux.vnet.ibm.com>
> Reply-To: luisgpm@linux.vnet.ibm.com
>
> > But they're pseudo-registers; no target "supports" them because
> > they're not real registers. Are you trying to say that some targets
> > have hardware support for decimal floating point, and you want to make
> > sure that these pseudo registers only show up on targets that have
> > such hardware support? If so I'd appreciate it if you could change
> > the comments to reflect that.
>
> The idea is to have a "decimal128" feature meaning that we're supposed
> to show these pseudo-registers for ppc32 and ppc64, similar to the way
> the EV registers work on the e500, except that we have (in the e500) 32
> of those being real registers and the other 32 being pseudo-registers.
> All those 64 registers sum up to create a single set of 32 64-bit
> registers (power-spe feature).
But that's a real hardware feature. It also controls the
pseudo-registers because it doesn't make sense to show those without
the real registers.
> > There are no software implementations that use the floating-point
> > registers in the same way as the hardware implementation does?
>
> Yes, there is. This would work the same way with software
> implementations, that is, we would have the same parameter passing
> scheme using pairs of FP registers.
In that case, I think you should just add the decimal floating-point
pseudo-registers unconditionally.
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2008-01-18 15:43 ` Luis Machado
2008-01-18 16:12 ` Mark Kettenis
@ 2008-01-19 0:04 ` Daniel Jacobowitz
2008-01-21 14:55 ` Thiago Jung Bauermann
1 sibling, 1 reply; 31+ messages in thread
From: Daniel Jacobowitz @ 2008-01-19 0:04 UTC (permalink / raw)
To: Luis Machado; +Cc: Thiago Jung Bauermann, gdb-patches
On Fri, Jan 18, 2008 at 01:42:34PM -0200, Luis Machado wrote:
> - /* These are the only pseudo-registers we support. */
> - gdb_assert (tdep->ppc_ev0_regnum >= 0
> - && regnum >= tdep->ppc_ev0_regnum
> - && regnum < tdep->ppc_ev0_regnum + 32);
> + /* These are the e500 pseudo-registers. */
> + if (tdep->ppc_ev0_regnum < 0
> + && regnum < tdep->ppc_ev0_regnum
> + && regnum >= tdep->ppc_ev0_regnum + 32)
> + return -1;
> +
> + /* These are the ppc decimal128 pseudo-registers. */
> + if (tdep->ppc_dl0_regnum < 0
> + && regnum < tdep->ppc_dl0_regnum
> + && regnum >= tdep->ppc_dl0_regnum + 16)
> + return -1;
This conversion is wrong - double-check the logic.
> @@ -3380,6 +3492,12 @@
> else
> have_altivec = 0;
>
> + feature = tdesc_find_feature (tdesc,
> + "org.gnu.gdb.power.dfp128");
> +
> + if (feature != NULL)
> + have_dfp128 = 1;
> +
> /* On machines supporting the SPE APU, the general-purpose registers
> are 64 bits long. There are SIMD vector instructions to treat them
> as pairs of floats, but the rest of the instruction set treats them
If the feature is not going to contain anything, I think it should be
a property of the floating point feature rather than an independent
feature - one which says "interpret these FP registers as DFP also",
<property name="dfp-registers"></property> or something similar.
That's how I would handle MMX versus SSE. However, since there is a
useful software implementation that uses the same registers, Mark is
right - we can just show them all the time.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2008-01-19 0:04 ` Daniel Jacobowitz
@ 2008-01-21 14:55 ` Thiago Jung Bauermann
2008-01-21 17:31 ` Mark Kettenis
0 siblings, 1 reply; 31+ messages in thread
From: Thiago Jung Bauermann @ 2008-01-21 14:55 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Luis Machado, gdb-patches
Hi,
Luis is on vacation at the moment, so I'll answer this for him...
On Fri, 2008-01-18 at 19:04 -0500, Daniel Jacobowitz wrote:
> If the feature is not going to contain anything, I think it should be
> a property of the floating point feature rather than an independent
> feature - one which says "interpret these FP registers as DFP also",
> <property name="dfp-registers"></property> or something similar.
>
> That's how I would handle MMX versus SSE. However, since there is a
> useful software implementation that uses the same registers, Mark is
> right - we can just show them all the time.
Yes, even for software decimal float implementations the calling
convention for PowerPC. is to put _Decimal128 in a pair of float
registers
I was talking to Luis about this, and he suggested an approach other
than using pseudo registers: create a way to make GDB consider two
consecutive registers as contiguous data. Since there are other types
that are also passed in consecutive registers (e.g., long long,
soft-float, IBM lon double), this mechanism would be more useful. I
think this is a good idea.
Perhaps some syntax could be created, like:
(gdb) print {_Decimal128} $f2,$f3
$1 = 1.2
What do you think?
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Printing decimal128 types out of registers
2008-01-21 14:55 ` Thiago Jung Bauermann
@ 2008-01-21 17:31 ` Mark Kettenis
2008-01-23 15:39 ` Thiago Jung Bauermann
0 siblings, 1 reply; 31+ messages in thread
From: Mark Kettenis @ 2008-01-21 17:31 UTC (permalink / raw)
To: bauerman; +Cc: drow, luisgpm, gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Date: Mon, 21 Jan 2008 12:54:34 -0200
>
> I was talking to Luis about this, and he suggested an approach other
> than using pseudo registers: create a way to make GDB consider two
> consecutive registers as contiguous data. Since there are other types
> that are also passed in consecutive registers (e.g., long long,
> soft-float, IBM lon double), this mechanism would be more useful. I
> think this is a good idea.
There's nothing wrong with the pseudo-register approach. In fact it
is used on many other architectures. For example sparc64, where pairs
of single-precision floating point numbers are used for
double-precision, and four registers are used for quadruple precision.
And on i386 we have the MMX registers that provide a different view on
the floating-point registers. I only think adding the whole tdesc
machinery around it is a bit too much.
Now PowerPC assembler is silly, and alows you to specify registers by
number instead of names. But most people actually rN for the general
purpose registers and fN for the floating-point registers. If dlN is
a widely accepted name for the decimal float registers, I think those
registers should be added.
> Perhaps some syntax could be created, like:
>
> (gdb) print {_Decimal128} $f2,$f3
> $1 = 1.2
>
> What do you think?
I'm not sure how this would fit into the expression parser. t might
get really ugly.
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Printing decimal128 types out of registers
2008-01-21 17:31 ` Mark Kettenis
@ 2008-01-23 15:39 ` Thiago Jung Bauermann
0 siblings, 0 replies; 31+ messages in thread
From: Thiago Jung Bauermann @ 2008-01-23 15:39 UTC (permalink / raw)
To: Mark Kettenis; +Cc: drow, luisgpm, gdb-patches
On Mon, 2008-01-21 at 18:30 +0100, Mark Kettenis wrote:
> There's nothing wrong with the pseudo-register approach. In fact it
> is used on many other architectures. For example sparc64, where pairs
> of single-precision floating point numbers are used for
> double-precision, and four registers are used for quadruple precision.
> And on i386 we have the MMX registers that provide a different view on
> the floating-point registers. I only think adding the whole tdesc
> machinery around it is a bit too much.
Ah, ok. I had misunderstood.
> If dlN is
> a widely accepted name for the decimal float registers, I think those
> registers should be added.
Actually, it's not a "widely accepted name". dl is the suffix used to
indicate _Decimal128 constants in C, so Luis chose it for the register
names as well.
The Power ISA uses a notation FRXp, where p for "register pair". The
instructions use the number of the first float register in the pair. We
could use $f0p to refer to register pair starting at $f0, but I'm not
sure it would be more intuitive than $dl0. I guess in both cases the
user would need to have previous knowledge or look it up in the manual.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2008-01-17 19:36 ` Thiago Jung Bauermann
2008-01-18 15:43 ` Luis Machado
@ 2008-01-21 17:54 ` Daniel Jacobowitz
2008-01-23 15:11 ` Thiago Jung Bauermann
1 sibling, 1 reply; 31+ messages in thread
From: Daniel Jacobowitz @ 2008-01-21 17:54 UTC (permalink / raw)
To: Thiago Jung Bauermann, Mark Kettenis; +Cc: Luis Machado, gdb-patches
On Mon, Jan 21, 2008 at 12:54:34PM -0200, Thiago Jung Bauermann wrote:
> Yes, even for software decimal float implementations the calling
> convention for PowerPC. is to put _Decimal128 in a pair of float
> registers
This, by itself, does not mean we need to be able to display two
registers as a _Decimal128. We will still be able to display a named
argument in two registers as _Decimal128, because the debug
information will (presumably) show it as two pieces in two registers
using DW_OP_piece.
There's no way to do math on a _Decimal128 value in two FP registers
without the hardware support. 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.
> I was talking to Luis about this, and he suggested an approach other
> than using pseudo registers: create a way to make GDB consider two
> consecutive registers as contiguous data. Since there are other types
> that are also passed in consecutive registers (e.g., long long,
> soft-float, IBM lon double), this mechanism would be more useful. I
> think this is a good idea.
This is like stepping backwards in time. We used to treat consecutive
registers as a big data blob and it was a terrible mess ... if you
want to examine typed multi-register values, I suggest leaving any
"consecutive" requirement out of the picture.
On Mon, Jan 21, 2008 at 06:30:16PM +0100, Mark Kettenis wrote:
> > Perhaps some syntax could be created, like:
> >
> > (gdb) print {_Decimal128} $f2,$f3
> > $1 = 1.2
> >
> > What do you think?
>
> I'm not sure how this would fit into the expression parser. t might
> get really ugly.
Definitely agreed. Maybe an explicit command to create a name for a
group of registers in order, using the same underlying mechanism we
use for DWARF.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Printing decimal128 types out of registers
2008-01-21 17:54 ` Daniel Jacobowitz
@ 2008-01-23 15:11 ` Thiago Jung Bauermann
2008-01-23 15:20 ` Daniel Jacobowitz
0 siblings, 1 reply; 31+ messages in thread
From: Thiago Jung Bauermann @ 2008-01-23 15:11 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Mark Kettenis, Luis Machado, gdb-patches
On Mon, 2008-01-21 at 12:54 -0500, Daniel Jacobowitz wrote:
> On Mon, Jan 21, 2008 at 12:54:34PM -0200, Thiago Jung Bauermann wrote:
> > Yes, even for software decimal float implementations the calling
> > convention for PowerPC. is to put _Decimal128 in a pair of float
> > registers
>
> This, by itself, does not mean we need to be able to display two
> registers as a _Decimal128. We will still be able to display a named
> argument in two registers as _Decimal128, because the debug
> information will (presumably) show it as two pieces in two registers
> using DW_OP_piece. There's no way to do math on a _Decimal128 value
> in two FP registers without the hardware support.
Ok, makes sense. The point where the _Decimal128 is copied from memory
into the two registers should be close to the function call site so it
wouldn't be hard to track it down and print the value from memory (when
no debug info is available).
> 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.
That would be the Power6 processor. In Linux, I can make the distinction
using the auxiliary vector:
AT_PLATFORM: power6
Or even better:
AT_HWCAP: dfp arch_2_05 ic_snoop smt mmu fpu altivec ppc64 ppc32
I don't know if this would work for other OSs (and I don't know if other
OSs have or will have DFP support). Is this a good method to determine
when to show the pseudo registers?
> > I was talking to Luis about this, and he suggested an approach other
> > than using pseudo registers: create a way to make GDB consider two
> > consecutive registers as contiguous data. Since there are other types
> > that are also passed in consecutive registers (e.g., long long,
> > soft-float, IBM lon double), this mechanism would be more useful. I
> > think this is a good idea.
>
> This is like stepping backwards in time. We used to treat consecutive
> registers as a big data blob and it was a terrible mess ... if you
> want to examine typed multi-register values, I suggest leaving any
> "consecutive" requirement out of the picture.
I mentioned "consecutive" to keep it simpler, but if a more general
mechanism is useful, that's ok.
> On Mon, Jan 21, 2008 at 06:30:16PM +0100, Mark Kettenis wrote:
> > > Perhaps some syntax could be created, like:
> > >
> > > (gdb) print {_Decimal128} $f2,$f3
> > > $1 = 1.2
> > >
> > > What do you think?
> >
> > I'm not sure how this would fit into the expression parser. t might
> > get really ugly.
>
> Definitely agreed. Maybe an explicit command to create a name for a
> group of registers in order, using the same underlying mechanism we
> use for DWARF.
Looks like an interesting feature. But since pseudo registers seem to be
the way to go in the DFP case, this will have to stay in the wishlist
for now...
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Printing decimal128 types out of registers
2008-01-23 15:11 ` Thiago Jung Bauermann
@ 2008-01-23 15:20 ` Daniel Jacobowitz
2008-01-23 16:56 ` Thiago Jung Bauermann
2008-01-30 15:46 ` Thiago Jung Bauermann
0 siblings, 2 replies; 31+ messages in thread
From: Daniel Jacobowitz @ 2008-01-23 15:20 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: Mark Kettenis, Luis Machado, gdb-patches
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.
>
> That would be the Power6 processor. In Linux, I can make the distinction
> using the auxiliary vector:
>
> AT_PLATFORM: power6
>
> Or even better:
>
> AT_HWCAP: dfp arch_2_05 ic_snoop smt mmu fpu altivec ppc64 ppc32
>
> I don't know if this would work for other OSs (and I don't know if other
> OSs have or will have DFP support). Is this a good method to determine
> when to show the pseudo registers?
Here's one (of many) possible ways you could do it. Define an
appropriate property in an XML file for Power6, and add that to the
list of built-in descriptions just like the existing ones. In
ppc-linux-nat.c and in gdbserver, check the auxv vector for the
dfp capability. If it's present, return the Power6 description.
Other non-Linux targets can handle this in the appropriate way
for each target.
For the gdbserver part you'd probably want to wait until Ulrich's
biarch patches go in; that may simplify it.
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.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2008-01-23 15:20 ` Daniel Jacobowitz
@ 2008-01-23 16:56 ` Thiago Jung Bauermann
2008-01-30 15:46 ` Thiago Jung Bauermann
1 sibling, 0 replies; 31+ messages in thread
From: Thiago Jung Bauermann @ 2008-01-23 16:56 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Mark Kettenis, Luis Machado, gdb-patches
On Wed, 2008-01-23 at 10:20 -0500, Daniel Jacobowitz wrote:
> Here's one (of many) possible ways you could do it. Define an
> appropriate property in an XML file for Power6, and add that to the
> list of built-in descriptions just like the existing ones. In
> ppc-linux-nat.c and in gdbserver, check the auxv vector for the
> dfp capability. If it's present, return the Power6 description.
> Other non-Linux targets can handle this in the appropriate way
> for each target.
>
> For the gdbserver part you'd probably want to wait until Ulrich's
> biarch patches go in; that may simplify it.
I'll try this. Thanks for the suggestion.
> 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.
Agreed.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2008-01-23 15:20 ` Daniel Jacobowitz
2008-01-23 16:56 ` Thiago Jung Bauermann
@ 2008-01-30 15:46 ` Thiago Jung Bauermann
2008-01-30 16:45 ` Thiago Jung Bauermann
2008-01-30 18:27 ` Mark Kettenis
1 sibling, 2 replies; 31+ messages in thread
From: Thiago Jung Bauermann @ 2008-01-30 15:46 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Mark Kettenis, Luis Machado, gdb-patches
[-- 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"
+
+}
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Printing decimal128 types out of registers
2008-01-30 15:46 ` Thiago Jung Bauermann
@ 2008-01-30 16:45 ` Thiago Jung Bauermann
2008-01-30 18:27 ` Mark Kettenis
1 sibling, 0 replies; 31+ messages in thread
From: Thiago Jung Bauermann @ 2008-01-30 16:45 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Mark Kettenis, Luis Machado, gdb-patches
On Wed, 2008-01-30 at 13:16 -0200, Thiago Jung Bauermann wrote:
> 2008-01-30 Thiago Jung Bauermann <bauerman@br.ibm.com>
Actually, this should be:
2008-01-30 Luis Machado <luisgpm@br.ibm.com>
Thiago Jung Bauermann <bauerman@br.ibm.com>
Sorry Luis! :-)
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2008-01-30 15:46 ` Thiago Jung Bauermann
2008-01-30 16:45 ` Thiago Jung Bauermann
@ 2008-01-30 18:27 ` Mark Kettenis
2008-01-30 18:38 ` Thiago Jung Bauermann
1 sibling, 1 reply; 31+ messages in thread
From: Mark Kettenis @ 2008-01-30 18:27 UTC (permalink / raw)
To: bauerman; +Cc: drow, luisgpm, gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Date: Wed, 30 Jan 2008 13:16:46 -0200
>
> > 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?
Looks mostly reasonable to me, but I don't see why you need
ppc_dl0_upper_regnum, and ppc_dl15_regnum.
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Printing decimal128 types out of registers
2008-01-30 18:27 ` Mark Kettenis
@ 2008-01-30 18:38 ` Thiago Jung Bauermann
2008-01-30 20:28 ` Mark Kettenis
0 siblings, 1 reply; 31+ messages in thread
From: Thiago Jung Bauermann @ 2008-01-30 18:38 UTC (permalink / raw)
To: Mark Kettenis; +Cc: drow, luisgpm, gdb-patches
On Wed, 2008-01-30 at 19:11 +0100, Mark Kettenis wrote:
> > Is this ok?
>
> Looks mostly reasonable to me, but I don't see why you need
> ppc_dl0_upper_regnum, and ppc_dl15_regnum.
ppc_dl0_upper_regnum is used ppc_pseudo_register_{read,write}. Are you
saying that given it always has the value of ppc_fp0_regnum, I should
use that instead? Could be, but then there's the lack of symmetry in
using an fp variable in dl-related code. But that's minor.
ppcdl15_regnum is indeed unused. I kept it also for symmetry reasons,
since there's ppc_ev31_regnum. But it can be removed (specially if the
later is removed as well as you suggested).
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Printing decimal128 types out of registers
2008-01-30 18:38 ` Thiago Jung Bauermann
@ 2008-01-30 20:28 ` Mark Kettenis
2008-01-30 21:26 ` Thiago Jung Bauermann
0 siblings, 1 reply; 31+ messages in thread
From: Mark Kettenis @ 2008-01-30 20:28 UTC (permalink / raw)
To: bauerman; +Cc: drow, luisgpm, gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Cc: drow@false.org, luisgpm@linux.vnet.ibm.com, gdb-patches@sourceware.org
> Date: Wed, 30 Jan 2008 16:30:24 -0200
> X-XS4ALL-DNSBL-Checked: mxdrop125.xs4all.nl checked 32.104.18.26 against DNS blacklists
> X-CNFS-Analysis: v=1.0 c=1 a=IUiVJ43dWc4A:15 a=QNG5IYMOGygA:10
> a=32zfua8Jo/FoLADJBaZU6A==:17 a=TUX4L2OknBXofI9ZbzkA:9
> a=kQGOXI3pO-Bphn8UE8AA:7 a=lLSZ6TJ2nqydr84DMUAV6pK8bCYA:4
> a=LY0hPdMaydYA:10
> X-Virus-Scanned: by XS4ALL Virus Scanner
> X-XS4ALL-Spam-Score: -0.0 () SPF_PASS
> X-XS4ALL-Spam: NO
> Envelope-To: mark.kettenis@xs4all.nl
>
> On Wed, 2008-01-30 at 19:11 +0100, Mark Kettenis wrote:
> > > Is this ok?
> >
> > Looks mostly reasonable to me, but I don't see why you need
> > ppc_dl0_upper_regnum, and ppc_dl15_regnum.
>
> ppc_dl0_upper_regnum is used ppc_pseudo_register_{read,write}. Are you
> saying that given it always has the value of ppc_fp0_regnum, I should
> use that instead? Could be, but then there's the lack of symmetry in
> using an fp variable in dl-related code. But that's minor.
Yes, I think that using ppc_fp0_regnum is better, since it makes it
explicit in the code that the decimal float (pseudo) registers are
just a different representation of the floating point registers.
> ppcdl15_regnum is indeed unused. I kept it also for symmetry reasons,
> since there's ppc_ev31_regnum. But it can be removed (specially if the
> later is removed as well as you suggested).
Yes, that was what I was thinking. The less uneeded clutter, the better.
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Printing decimal128 types out of registers
2008-01-30 20:28 ` Mark Kettenis
@ 2008-01-30 21:26 ` Thiago Jung Bauermann
2008-01-30 21:39 ` Ulrich Weigand
` (2 more replies)
0 siblings, 3 replies; 31+ messages in thread
From: Thiago Jung Bauermann @ 2008-01-30 21:26 UTC (permalink / raw)
To: Mark Kettenis; +Cc: drow, luisgpm, gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1064 bytes --]
On Wed, 2008-01-30 at 19:52 +0100, Mark Kettenis wrote:
> > From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> > ppc_dl0_upper_regnum is used ppc_pseudo_register_{read,write}. Are you
> > saying that given it always has the value of ppc_fp0_regnum, I should
> > use that instead? Could be, but then there's the lack of symmetry in
> > using an fp variable in dl-related code. But that's minor.
>
> Yes, I think that using ppc_fp0_regnum is better, since it makes it
> explicit in the code that the decimal float (pseudo) registers are
> just a different representation of the floating point registers.
>
> > ppcdl15_regnum is indeed unused. I kept it also for symmetry reasons,
> > since there's ppc_ev31_regnum. But it can be removed (specially if the
> > later is removed as well as you suggested).
>
> Yes, that was what I was thinking. The less uneeded clutter, the better.
Ok, removed those. I also refreshed it against the reworked SPE macro
cleanup patch. What about this?
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
[-- Attachment #2: dec128-regs-rev2.diff --]
[-- Type: text/x-patch, Size: 18562 bytes --]
2008-01-30 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 5d0fad100af7 gdb/doc/gdb.texinfo
--- a/gdb/doc/gdb.texinfo Wed Jan 30 16:49:16 2008 -0200
+++ b/gdb/doc/gdb.texinfo Wed Jan 30 18:54:00 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 5d0fad100af7 gdb/infcmd.c
--- a/gdb/infcmd.c Wed Jan 30 16:49:16 2008 -0200
+++ b/gdb/infcmd.c Wed Jan 30 18:54:00 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 5d0fad100af7 gdb/ppc-tdep.h
--- a/gdb/ppc-tdep.h Wed Jan 30 16:49:16 2008 -0200
+++ b/gdb/ppc-tdep.h Wed Jan 30 18:54:00 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 5d0fad100af7 gdb/rs6000-tdep.c
--- a/gdb/rs6000-tdep.c Wed Jan 30 16:49:16 2008 -0200
+++ b/gdb/rs6000-tdep.c Wed Jan 30 18:54:00 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_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 (current_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 5d0fad100af7 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 18:54:00 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 5d0fad100af7 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 18:54:00 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"
+
+}
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Printing decimal128 types out of registers
2008-01-30 21:26 ` Thiago Jung Bauermann
@ 2008-01-30 21:39 ` Ulrich Weigand
2008-01-31 14:47 ` Thiago Jung Bauermann
2008-01-30 21:42 ` Mark Kettenis
2008-01-30 23:03 ` Eli Zaretskii
2 siblings, 1 reply; 31+ messages in thread
From: Ulrich Weigand @ 2008-01-30 21:39 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: Mark Kettenis, drow, luisgpm, gdb-patches
Hi Tiago,
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) ...
Bye,
Ulrich
--
Dr. Ulrich Weigand
GNU Toolchain for Linux on System z and Cell BE
Ulrich.Weigand@de.ibm.com
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2008-01-30 21:39 ` Ulrich Weigand
@ 2008-01-31 14:47 ` Thiago Jung Bauermann
2008-01-31 15:06 ` Ulrich Weigand
0 siblings, 1 reply; 31+ messages in thread
From: Thiago Jung Bauermann @ 2008-01-31 14:47 UTC (permalink / raw)
To: Ulrich Weigand; +Cc: Mark Kettenis, drow, luisgpm, gdb-patches
[-- Attachment #1: Type: text/plain, Size: 443 bytes --]
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
[-- Attachment #2: dec128-regs-rev3.diff --]
[-- Type: text/x-patch, Size: 18538 bytes --]
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"
+
+}
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2008-01-30 21:26 ` Thiago Jung Bauermann
2008-01-30 21:39 ` Ulrich Weigand
@ 2008-01-30 21:42 ` Mark Kettenis
2008-01-30 23:03 ` Eli Zaretskii
2 siblings, 0 replies; 31+ messages in thread
From: Mark Kettenis @ 2008-01-30 21:42 UTC (permalink / raw)
To: bauerman; +Cc: drow, luisgpm, gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Date: Wed, 30 Jan 2008 19:02:55 -0200
>
> On Wed, 2008-01-30 at 19:52 +0100, Mark Kettenis wrote:
> > > From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> > > ppc_dl0_upper_regnum is used ppc_pseudo_register_{read,write}. Are you
> > > saying that given it always has the value of ppc_fp0_regnum, I should
> > > use that instead? Could be, but then there's the lack of symmetry in
> > > using an fp variable in dl-related code. But that's minor.
> >
> > Yes, I think that using ppc_fp0_regnum is better, since it makes it
> > explicit in the code that the decimal float (pseudo) registers are
> > just a different representation of the floating point registers.
> >
> > > ppcdl15_regnum is indeed unused. I kept it also for symmetry reasons,
> > > since there's ppc_ev31_regnum. But it can be removed (specially if the
> > > later is removed as well as you suggested).
> >
> > Yes, that was what I was thinking. The less uneeded clutter, the better.
>
> Ok, removed those. I also refreshed it against the reworked SPE macro
> cleanup patch. What about this?
Looks fine to me (as does the SPE macro cleanup diff).
> 2008-01-30 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.
^ permalink raw reply [flat|nested] 31+ messages in thread* Re: Printing decimal128 types out of registers
2008-01-30 21:26 ` Thiago Jung Bauermann
2008-01-30 21:39 ` Ulrich Weigand
2008-01-30 21:42 ` Mark Kettenis
@ 2008-01-30 23:03 ` Eli Zaretskii
2008-01-31 15:44 ` Thiago Jung Bauermann
2 siblings, 1 reply; 31+ messages in thread
From: Eli Zaretskii @ 2008-01-30 23:03 UTC (permalink / raw)
To: Thiago Jung Bauermann; +Cc: mark.kettenis, drow, luisgpm, gdb-patches
> From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> Cc: drow@false.org, luisgpm@linux.vnet.ibm.com, gdb-patches@sourceware.org
> Date: Wed, 30 Jan 2008 19:02:55 -0200
>
> Ok, removed those. I also refreshed it against the reworked SPE macro
> cleanup patch. What about this?
The patch for the manual is okay. Thanks.
^ permalink raw reply [flat|nested] 31+ messages in thread
* Re: Printing decimal128 types out of registers
2008-01-30 23:03 ` Eli Zaretskii
@ 2008-01-31 15:44 ` Thiago Jung Bauermann
0 siblings, 0 replies; 31+ messages in thread
From: Thiago Jung Bauermann @ 2008-01-31 15:44 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: mark.kettenis, drow, luisgpm, gdb-patches
On Wed, 2008-01-30 at 23:58 +0200, Eli Zaretskii wrote:
> > From: Thiago Jung Bauermann <bauerman@br.ibm.com>
> > Cc: drow@false.org, luisgpm@linux.vnet.ibm.com, gdb-patches@sourceware.org
> > Date: Wed, 30 Jan 2008 19:02:55 -0200
> >
> > Ok, removed those. I also refreshed it against the reworked SPE macro
> > cleanup patch. What about this?
>
> The patch for the manual is okay. Thanks.
Thanks for the review.
--
[]'s
Thiago Jung Bauermann
Software Engineer
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 31+ messages in thread
end of thread, other threads:[~2008-01-31 15:02 UTC | newest]
Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-07 19:33 [PATCH] PPC - Printing Decimal 128 types out of registers Luis Machado
2007-11-26 21:40 ` Luis Machado
2007-12-26 12:42 ` [PING] " Luis Machado
2008-01-17 19:03 ` Printing decimal128 " Luis Machado
2008-01-17 19:36 ` Thiago Jung Bauermann
2008-01-18 15:43 ` Luis Machado
2008-01-18 16:12 ` Mark Kettenis
2008-01-18 16:38 ` Luis Machado
2008-01-18 17:20 ` Mark Kettenis
2008-01-18 18:52 ` Luis Machado
2008-01-18 19:54 ` Mark Kettenis
2008-01-19 0:04 ` Daniel Jacobowitz
2008-01-21 14:55 ` Thiago Jung Bauermann
2008-01-21 17:31 ` Mark Kettenis
2008-01-23 15:39 ` Thiago Jung Bauermann
2008-01-21 17:54 ` Daniel Jacobowitz
2008-01-23 15:11 ` Thiago Jung Bauermann
2008-01-23 15:20 ` Daniel Jacobowitz
2008-01-23 16:56 ` Thiago Jung Bauermann
2008-01-30 15:46 ` Thiago Jung Bauermann
2008-01-30 16:45 ` Thiago Jung Bauermann
2008-01-30 18:27 ` Mark Kettenis
2008-01-30 18:38 ` Thiago Jung Bauermann
2008-01-30 20:28 ` Mark Kettenis
2008-01-30 21:26 ` Thiago Jung Bauermann
2008-01-30 21:39 ` Ulrich Weigand
2008-01-31 14:47 ` Thiago Jung Bauermann
2008-01-31 15:06 ` Ulrich Weigand
2008-01-30 21:42 ` Mark Kettenis
2008-01-30 23:03 ` Eli Zaretskii
2008-01-31 15:44 ` Thiago Jung Bauermann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox