for reference: E500 Dwarf piece simplifier

Jim Blandy
2004-08-10T20:09:33Z

This adds a Dwarf piece simplifier that recognizes piece lists that
refer to E500 vector registers. It's based on the patch I posted to
the discussion here:

http://sources.redhat.com/ml/gdb/2004-08/msg00153.html

Since we're still discussing whether we want to take this piece-
simplification approach at all, rather than waiting for full scattered
value support in core GDB, this post isn't a request for approval,
although review is always welcome. It's more to get the work out
there and let people see what a piece simplifier would look like.

This is all based on the dwarf2expr piece interface I posted here:

http://sources.redhat.com/ml/gdb-patches/2004-08/msg00351.html

2004-08-09 Jim Blandy <jimb@redhat.com>

* rs6000-tdep.c: #include "dwarf2expr.h".
(dwarf_piece_is_ev_upper_reg, dwarf_piece_is_gpr)
(e500_dwarf_simplify_register_pieces): New functions.
(rs6000_gdbarch_init): If the architecture is E500, register
e500_dwarf_simplify_register_pieces.
* Makefile.in (rs6000-tdep.o): Update dependencies.

diff -crp -x '*~' -x '.#*' -x CVS gdb/rs6000-tdep.c gdb/rs6000-tdep.c
*** gdb/rs6000-tdep.c 2004-08-09 19:29:29.000000000 -0500
--- gdb/rs6000-tdep.c 2004-08-10 11:28:43.000000000 -0500
***************
*** 40,45 ****
--- 40,46 ----
#include "sim-regno.h"
#include "gdb/sim-ppc.h"
#include "reggroups.h"
+ #include "dwarf2expr.h"

#include "libbfd.h" /* for bfd_default_set_arch_mach */
#include "coff/internal.h" /* for libcoff.h */
*************** e500_register_reggroup_p (struct gdbarch
*** 2005,2010 ****
--- 2006,2089 ----
return default_register_reggroup_p (gdbarch, regnum, group);
}

+ /* Return true if PIECE is a SPE upper-half register for ARCH.
+ Remember that pieces use the Dwarf register numbering. */
+ static int
+ dwarf_piece_is_ev_upper_reg (struct gdbarch *arch,
+ struct dwarf_expr_piece *piece)
+ {
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+
+ return (piece->in_reg
+ && 1200 <= piece->value
+ && piece->value < 1200 + ppc_num_gprs
+ && piece->size == register_size (arch,
+ (piece->value - 1200
+ + tdep->ppc_ev0_upper_regnum)));
+ }
+
+ /* Return true if PIECE is a full GPR in ARCH.
+ Remember that pieces use the Dwarf register numbering. */
+ static int
+ dwarf_piece_is_gpr (struct gdbarch *arch,
+ struct dwarf_expr_piece *piece)
+ {
+ struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+
+ return (piece->in_reg
+ && 0 <= piece->value
+ && piece->value < ppc_num_gprs
+ && (piece->size
+ == register_size (arch, piece->value + tdep->ppc_gp0_regnum)));
+ }
+
+ static int
+ e500_dwarf_simplify_register_pieces (struct gdbarch *gdbarch,
+ int num_pieces,
+ struct dwarf_expr_piece *pieces)
+ {
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (num_pieces == 2)
+ {
+ int low, high;
+
+ /* Pieces are listed in order of increasing addresses, so the
+ endianness affects the order of the most- and least-
+ significant halves. */
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ high = 0, low = 1;
+ else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
+ low = 0, high = 1;
+ else
+ internal_error (__FILE__, __LINE__,
+ "fetch_register: unexpected byte order: %d",
+ gdbarch_byte_order (gdbarch));
+
+ /* An SPE vector register is the concatenation of an "upper
+ half" register with a GPR, each four bytes long. */
+ if (dwarf_piece_is_ev_upper_reg (gdbarch, &pieces[high])
+ && dwarf_piece_is_gpr (gdbarch, &pieces[low])
+ && (pieces[high].value - 1200 == pieces[low].value))
+ /* Return the corresponding 64-bit 'ev' pseudo-register. */
+ return tdep->ppc_ev0_regnum + pieces[low].value;
+
+ /* long long values are sometimes placed in pairs of consecutive
+ registers. The lower-addressed end of the value is always
+ assigned the lower-numbered register, so we don't need to
+ worry about endianness here. */
+ else if (dwarf_piece_is_gpr (gdbarch, &pieces[0])
+ && dwarf_piece_is_gpr (gdbarch, &pieces[1])
+ && pieces[0].value + 1 == pieces[1].value)
+ return tdep->ppc_gp0_regnum + pieces[0].value;
+
+ else
+ return -1;
+ }
+ else
+ return -1;
+ }
+
/* Convert a DBX STABS register number to a GDB register number. */
static int
rs6000_stab_reg_to_regnum (int num)
*************** rs6000_gdbarch_init (struct gdbarch_info
*** 3172,3177 ****
--- 3251,3258 ----
set_gdbarch_pseudo_register_read (gdbarch, e500_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, e500_pseudo_register_write);
set_gdbarch_register_reggroup_p (gdbarch, e500_register_reggroup_p);
+ set_gdbarch_dwarf_simplify_register_pieces
+ (gdbarch, e500_dwarf_simplify_register_pieces);
break;

case bfd_mach_ppc64: