powerpc-linux biarch corefile support
Alan Modra
amodra@bigpond.net.au
Sat Aug 25 01:23:00 GMT 2007
On Sat, Apr 28, 2007 at 06:19:36PM +0200, Ulrich Weigand wrote:
> Why don't we push the task of clearing individual registers down
> to ppc_supply_reg and ppc_collect_reg in rs6000-nat.c? Have their
> callers always provide them with an "offset" value pointing to the
> start of the full field in REGS, and provide an extra "size" value
> denoting the length of the field in REGS.
>
> The helper functions can compare that size with GDB's notion of
> the register_size, and if it is bigger (it cannot be smaller),
> supply only the right part of the field, and zero out the left
> part of the field when collecting.
>
> The callers of ppc_supply_reg and ppc_collect_reg should be able
> to provide that new size value using offsets->gpr_size or fixed
> values.
>
> Note that this should make ppc64_32_linux_reg_offsets unnecessary,
> you'll need to always use ppc64_linux_reg_offsets on a 64-bit host.
OK, that's what I've done in the following patch.
Looking first at the generic rs6000 changes, these are:
1) Add a "gpr_size" field to "struct ppc_reg_offsets" so that the
collect_regset and supply_regset functions will work with both
32-bit and 64-bit regsets. We can't simply use tdep->wordsize to
deduce the size of registers, because in some cases
(eg. supply_gregset and fill_gregset in ppc-linux-nat.c) the size
we want is "sizeof (long)" rather than the target wordsize.
2) The low level ppc_supply_reg and ppc_collect_reg functions are
changed as per Ulrich's suggestion, to zero pad a larger register
field as necessary.
3) I reorganized ppc_supply_gregset et al to be a little more
efficient. It seemed silly to run around a loop to find a gpr/fpr
offset when transferring one register. This particular change also
fixes a bug in one of the register offsets, and removes uses of
current_gdbarch where the gdbarch is available from the regcache.
4) ppc_supply_fpregset and ppc_collect_fpregset had an assert that
the target had a fp unit, and callers generally tested the same.
I changed the assert to instead return if !ppc_floating_point_unit_p
and removed the caller tests. It seems silly to duplicate the
tests, and I believe it is correct for ppc_supply_fpregset and
ppc_collect_fpregset to do nothing when the target has no fp unit.
It is certainly consistent with other cases where one or more
registers are not present in a target.
With these changes in place quite a lot of ppc-linux-nat.c and
ppc-linux-tdep.c can disappear, and we get biarch core file capability.
Note that without (4) above, we need a wrapper for ppc_supply_fpregset
and ppc_collect_fpregset so that these functions aren't called for
e500.
I removed the FIXMEs in ppcobsd-tdep.c because that seems appropriate
in line with removing the asserts in (4). I left the other two
similar FIXMEs (in ppcobsd-nat.c and ppcnbsd-nat.c) as code there (and
in the callers of getfpregs_supplies) will need updating to handle
e500.
* ppc-linux-nat.c (right_fill_reg): Delete.
(supply_gregset): Use ppc_supply_gregset.
(supply_fpregset): Use ppc_supply_fpregset.
(fill_gregset): Use ppc_collect_gregset.
(fill_fpregset): Use ppc_collect_fpregset.
* ppc-linux-tdep.c (PPC_LINUX_PT_*): Don't define.
(right_supply_register, ppc_linux_supply_gregset): Delete.
(ppc32_linux_supply_gregset, ppc64_linux_supply_gregset): Delete.
(ppc_linux_supply_fpregset): Delete.
(ppc32_linux_reg_offsets, ppc64_linux_reg_offsets): New.
(ppc32_linux_gregset, ppc64_linux_gregset): Update to use reg offsets,
ppc_supply_gregset, and ppc_collect_gregset.
(ppc_linux_fpregset): Rename to ppc32_linux_fpregset and update.
(ppc_linux_gregset, ppc_linux_fpregset): New functions.
(ppc_linux_regset_from_core_section): Update.
* ppc-tdep.h (ppc_linux_gregset, ppc_linux_fpregset): Declare.
(ppc_linux_supply_gregset, ppc_linux_supply_fpregset): Delete.
(struct ppc_reg_offsets): Add "gpr_size" field.
* ppcobsd-tdep.c (ppcobsd_supply_gregset): Delete FIXME and assert.
(ppcobsd_collect_gregset): Likewise.
(_initialize_ppcnbsd_tdep): Init gpr_size.
* ppcnbsd-tdep.c (_initialize_ppcobsd_tdep): Likewise.
* rs6000-aix-tdep.c (rs6000_aix_supply_regset): Call
ppc_supply_fpregset without testing ppc_floating_point_unit_p.
(rs6000_aix_collect_regset): Similarly.
* rs6000-tdep.c (ppc_supply_reg): Add regsize param. Adjust offset
when regsize is larger than regcache register size.
(ppc_collect_reg): Similarly zero pad when regsize is larger than
regcache register size.
(ppc_greg_offset): New function, split out from..
(ppc_supply_gregset): ..here. Separate code handling all regs from
single reg case. Correct xer offset.
(ppc_fpreg_offset): New function, split out from..
(ppc_supply_fpregset): ..here. Separate code handling all regs from
single reg case.
(ppc_collect_gregset, ppc_collect_fpregset): Likewise.
(ppc_supply_fpregset, ppc_collect_fpregset): Don't assert we have
a fp unit, instead return if no fp.
Index: gdb/ppc-linux-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-linux-nat.c,v
retrieving revision 1.69
diff -u -p -r1.69 ppc-linux-nat.c
--- gdb/ppc-linux-nat.c 23 Aug 2007 18:08:36 -0000 1.69
+++ gdb/ppc-linux-nat.c 24 Aug 2007 13:08:20 -0000
@@ -901,101 +901,46 @@ ppc_linux_store_inferior_registers (stru
store_ppc_registers (regcache, tid);
}
+/* Functions for transferring registers between a gregset_t or fpregset_t
+ (see sys/ucontext.h) and gdb's regcache. The word size is that used
+ by the ptrace interface, not the current program's ABI. eg. If a
+ powerpc64-linux gdb is being used to debug a powerpc32-linux app, we
+ read or write 64-bit gregsets. This is to suit the host libthread_db. */
+
void
supply_gregset (struct regcache *regcache, const gdb_gregset_t *gregsetp)
{
- /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace
- interface, and not the wordsize of the program's ABI. */
- int wordsize = sizeof (long);
- ppc_linux_supply_gregset (regcache, -1, gregsetp,
- sizeof (gdb_gregset_t), wordsize);
-}
+ const struct regset *regset = ppc_linux_gregset (sizeof (long));
-static void
-right_fill_reg (const struct regcache *regcache, int regnum, void *reg)
-{
- /* NOTE: cagney/2003-11-25: This is the word size used by the ptrace
- interface, and not the wordsize of the program's ABI. */
- int wordsize = sizeof (long);
- /* Right fill the register. */
- regcache_raw_collect (regcache, regnum,
- ((bfd_byte *) reg
- + wordsize
- - register_size (current_gdbarch, regnum)));
+ ppc_supply_gregset (regset, regcache, -1, gregsetp, sizeof (*gregsetp));
}
void
fill_gregset (const struct regcache *regcache,
gdb_gregset_t *gregsetp, int regno)
{
- int regi;
- elf_greg_t *regp = (elf_greg_t *) gregsetp;
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
- const int elf_ngreg = 48;
-
-
- /* Start with zeros. */
- memset (regp, 0, elf_ngreg * sizeof (*regp));
-
- for (regi = 0; regi < ppc_num_gprs; regi++)
- {
- if ((regno == -1) || regno == tdep->ppc_gp0_regnum + regi)
- right_fill_reg (regcache, tdep->ppc_gp0_regnum + regi,
- (regp + PT_R0 + regi));
- }
-
- if ((regno == -1) || regno == gdbarch_pc_regnum (current_gdbarch))
- right_fill_reg (regcache, gdbarch_pc_regnum (current_gdbarch),
- regp + PT_NIP);
- if ((regno == -1) || regno == tdep->ppc_lr_regnum)
- right_fill_reg (regcache, tdep->ppc_lr_regnum, regp + PT_LNK);
- if ((regno == -1) || regno == tdep->ppc_cr_regnum)
- regcache_raw_collect (regcache, tdep->ppc_cr_regnum,
- regp + PT_CCR);
- if ((regno == -1) || regno == tdep->ppc_xer_regnum)
- regcache_raw_collect (regcache, tdep->ppc_xer_regnum,
- regp + PT_XER);
- if ((regno == -1) || regno == tdep->ppc_ctr_regnum)
- right_fill_reg (regcache, tdep->ppc_ctr_regnum, regp + PT_CTR);
-#ifdef PT_MQ
- if (((regno == -1) || regno == tdep->ppc_mq_regnum)
- && (tdep->ppc_mq_regnum != -1))
- right_fill_reg (regcache, tdep->ppc_mq_regnum, regp + PT_MQ);
-#endif
- if ((regno == -1) || regno == tdep->ppc_ps_regnum)
- right_fill_reg (regcache, tdep->ppc_ps_regnum, regp + PT_MSR);
+ const struct regset *regset = ppc_linux_gregset (sizeof (long));
+
+ ppc_collect_gregset (regset, regcache, regno, gregsetp, sizeof (*gregsetp));
}
void
supply_fpregset (struct regcache *regcache, const gdb_fpregset_t * fpregsetp)
{
- ppc_linux_supply_fpregset (NULL, regcache, -1, fpregsetp,
- sizeof (gdb_fpregset_t));
+ const struct regset *regset = ppc_linux_fpregset ();
+
+ ppc_supply_fpregset (regset, regcache, -1,
+ fpregsetp, sizeof (*fpregsetp));
}
-/* Given a pointer to a floating point register set in /proc format
- (fpregset_t *), update the register specified by REGNO from gdb's
- idea of the current floating point register set. If REGNO is -1,
- update them all. */
void
fill_fpregset (const struct regcache *regcache,
gdb_fpregset_t *fpregsetp, int regno)
{
- int regi;
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
- bfd_byte *fpp = (void *) fpregsetp;
-
- if (ppc_floating_point_unit_p (current_gdbarch))
- {
- for (regi = 0; regi < ppc_num_fprs; regi++)
- {
- if ((regno == -1) || (regno == tdep->ppc_fp0_regnum + regi))
- regcache_raw_collect (regcache, tdep->ppc_fp0_regnum + regi,
- fpp + 8 * regi);
- }
- if (regno == -1 || regno == tdep->ppc_fpscr_regnum)
- right_fill_reg (regcache, tdep->ppc_fpscr_regnum, (fpp + 8 * 32));
- }
+ const struct regset *regset = ppc_linux_fpregset ();
+
+ ppc_collect_fpregset (regset, regcache, regno,
+ fpregsetp, sizeof (*fpregsetp));
}
void _initialize_ppc_linux_nat (void);
Index: gdb/ppc-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v
retrieving revision 1.87
diff -u -p -r1.87 ppc-linux-tdep.c
--- gdb/ppc-linux-tdep.c 23 Aug 2007 18:08:36 -0000 1.87
+++ gdb/ppc-linux-tdep.c 24 Aug 2007 13:08:21 -0000
@@ -38,51 +38,6 @@
#include "frame-unwind.h"
#include "tramp-frame.h"
-/* From <asm/ptrace.h>, values for PT_NIP, PT_R1, and PT_LNK */
-#define PPC_LINUX_PT_R0 0
-#define PPC_LINUX_PT_R1 1
-#define PPC_LINUX_PT_R2 2
-#define PPC_LINUX_PT_R3 3
-#define PPC_LINUX_PT_R4 4
-#define PPC_LINUX_PT_R5 5
-#define PPC_LINUX_PT_R6 6
-#define PPC_LINUX_PT_R7 7
-#define PPC_LINUX_PT_R8 8
-#define PPC_LINUX_PT_R9 9
-#define PPC_LINUX_PT_R10 10
-#define PPC_LINUX_PT_R11 11
-#define PPC_LINUX_PT_R12 12
-#define PPC_LINUX_PT_R13 13
-#define PPC_LINUX_PT_R14 14
-#define PPC_LINUX_PT_R15 15
-#define PPC_LINUX_PT_R16 16
-#define PPC_LINUX_PT_R17 17
-#define PPC_LINUX_PT_R18 18
-#define PPC_LINUX_PT_R19 19
-#define PPC_LINUX_PT_R20 20
-#define PPC_LINUX_PT_R21 21
-#define PPC_LINUX_PT_R22 22
-#define PPC_LINUX_PT_R23 23
-#define PPC_LINUX_PT_R24 24
-#define PPC_LINUX_PT_R25 25
-#define PPC_LINUX_PT_R26 26
-#define PPC_LINUX_PT_R27 27
-#define PPC_LINUX_PT_R28 28
-#define PPC_LINUX_PT_R29 29
-#define PPC_LINUX_PT_R30 30
-#define PPC_LINUX_PT_R31 31
-#define PPC_LINUX_PT_NIP 32
-#define PPC_LINUX_PT_MSR 33
-#define PPC_LINUX_PT_CTR 35
-#define PPC_LINUX_PT_LNK 36
-#define PPC_LINUX_PT_XER 37
-#define PPC_LINUX_PT_CCR 38
-#define PPC_LINUX_PT_MQ 39
-#define PPC_LINUX_PT_FPR0 48 /* each FP reg occupies 2 slots in this space */
-#define PPC_LINUX_PT_FPR31 (PPC_LINUX_PT_FPR0 + 2*31)
-#define PPC_LINUX_PT_FPSCR (PPC_LINUX_PT_FPR0 + 2*32 + 1)
-
-
static CORE_ADDR
ppc_linux_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{
@@ -660,99 +615,85 @@ ppc_linux_convert_from_func_ptr_addr (st
return addr;
}
-static void
-right_supply_register (struct regcache *regcache, int wordsize, int regnum,
- const bfd_byte *buf)
-{
- regcache_raw_supply (regcache, regnum,
- (buf + wordsize - register_size (current_gdbarch, regnum)));
-}
-
-/* Extract the register values found in the WORDSIZED ABI GREGSET,
- storing their values in REGCACHE. Note that some are left-aligned,
- while others are right aligned. */
-
-void
-ppc_linux_supply_gregset (struct regcache *regcache,
- int regnum, const void *gregs, size_t size,
- int wordsize)
-{
- int regi;
- struct gdbarch *regcache_arch = get_regcache_arch (regcache);
- struct gdbarch_tdep *regcache_tdep = gdbarch_tdep (regcache_arch);
- const bfd_byte *buf = gregs;
-
- for (regi = 0; regi < ppc_num_gprs; regi++)
- right_supply_register (regcache, wordsize,
- regcache_tdep->ppc_gp0_regnum + regi,
- buf + wordsize * regi);
-
- right_supply_register (regcache, wordsize, gdbarch_pc_regnum (regcache_arch),
- buf + wordsize * PPC_LINUX_PT_NIP);
- right_supply_register (regcache, wordsize, regcache_tdep->ppc_lr_regnum,
- buf + wordsize * PPC_LINUX_PT_LNK);
- regcache_raw_supply (regcache, regcache_tdep->ppc_cr_regnum,
- buf + wordsize * PPC_LINUX_PT_CCR);
- regcache_raw_supply (regcache, regcache_tdep->ppc_xer_regnum,
- buf + wordsize * PPC_LINUX_PT_XER);
- regcache_raw_supply (regcache, regcache_tdep->ppc_ctr_regnum,
- buf + wordsize * PPC_LINUX_PT_CTR);
- if (regcache_tdep->ppc_mq_regnum != -1)
- right_supply_register (regcache, wordsize, regcache_tdep->ppc_mq_regnum,
- buf + wordsize * PPC_LINUX_PT_MQ);
- right_supply_register (regcache, wordsize, regcache_tdep->ppc_ps_regnum,
- buf + wordsize * PPC_LINUX_PT_MSR);
-}
+/* Regset descriptions. */
+static const struct ppc_reg_offsets ppc32_linux_reg_offsets =
+ {
+ /* General-purpose registers. */
+ /* .r0_offset = */ 0,
+ /* .gpr_size = */ 4,
+ /* .pc_offset = */ 128,
+ /* .ps_offset = */ 132,
+ /* .cr_offset = */ 152,
+ /* .lr_offset = */ 144,
+ /* .ctr_offset = */ 140,
+ /* .xer_offset = */ 148,
+ /* .mq_offset = */ 156,
+
+ /* Floating-point registers. */
+ /* .f0_offset = */ 0,
+ /* .fpscr_offset = */ 256 + 4,
+
+ /* AltiVec registers. */
+ /* .vr0_offset = */ 0,
+ /* .vrsave_offset = */ 512,
+ /* .vscr_offset = */ 512 + 12
+ };
-static void
-ppc32_linux_supply_gregset (const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *gregs, size_t size)
-{
- ppc_linux_supply_gregset (regcache, regnum, gregs, size, 4);
-}
+static const struct ppc_reg_offsets ppc64_linux_reg_offsets =
+ {
+ /* General-purpose registers. */
+ /* .r0_offset = */ 0,
+ /* .gpr_size = */ 8,
+ /* .pc_offset = */ 256,
+ /* .ps_offset = */ 264,
+ /* .cr_offset = */ 304,
+ /* .lr_offset = */ 288,
+ /* .ctr_offset = */ 280,
+ /* .xer_offset = */ 296,
+ /* .mq_offset = */ 312,
+
+ /* Floating-point registers. */
+ /* .f0_offset = */ 0,
+ /* .fpscr_offset = */ 256,
+
+ /* AltiVec registers. */
+ /* .vr0_offset = */ 0,
+ /* .vrsave_offset = */ 528,
+ /* .vscr_offset = */ 512 + 12
+ };
static struct regset ppc32_linux_gregset = {
- NULL, ppc32_linux_supply_gregset
+ &ppc32_linux_reg_offsets,
+ ppc_supply_gregset,
+ ppc_collect_gregset,
+ NULL
};
-static void
-ppc64_linux_supply_gregset (const struct regset *regset,
- struct regcache * regcache,
- int regnum, const void *gregs, size_t size)
-{
- ppc_linux_supply_gregset (regcache, regnum, gregs, size, 8);
-}
-
static struct regset ppc64_linux_gregset = {
- NULL, ppc64_linux_supply_gregset
+ &ppc64_linux_reg_offsets,
+ ppc_supply_gregset,
+ ppc_collect_gregset,
+ NULL
};
-void
-ppc_linux_supply_fpregset (const struct regset *regset,
- struct regcache * regcache,
- int regnum, const void *fpset, size_t size)
-{
- int regi;
- struct gdbarch *regcache_arch = get_regcache_arch (regcache);
- struct gdbarch_tdep *regcache_tdep = gdbarch_tdep (regcache_arch);
- const bfd_byte *buf = fpset;
-
- if (! ppc_floating_point_unit_p (regcache_arch))
- return;
-
- for (regi = 0; regi < ppc_num_fprs; regi++)
- regcache_raw_supply (regcache,
- regcache_tdep->ppc_fp0_regnum + regi,
- buf + 8 * regi);
-
- /* The FPSCR is stored in the low order word of the last
- doubleword in the fpregset. */
- regcache_raw_supply (regcache, regcache_tdep->ppc_fpscr_regnum,
- buf + 8 * 32 + 4);
+static struct regset ppc32_linux_fpregset = {
+ &ppc32_linux_reg_offsets,
+ ppc_supply_fpregset,
+ ppc_collect_fpregset,
+ NULL
+};
+
+const struct regset *
+ppc_linux_gregset (int wordsize)
+{
+ return wordsize == 8 ? &ppc64_linux_gregset : &ppc32_linux_gregset;
}
-static struct regset ppc_linux_fpregset = { NULL, ppc_linux_supply_fpregset };
+const struct regset *
+ppc_linux_fpregset (void)
+{
+ return &ppc32_linux_fpregset;
+}
static const struct regset *
ppc_linux_regset_from_core_section (struct gdbarch *core_arch,
@@ -767,7 +708,7 @@ ppc_linux_regset_from_core_section (stru
return &ppc64_linux_gregset;
}
if (strcmp (sect_name, ".reg2") == 0)
- return &ppc_linux_fpregset;
+ return &ppc32_linux_fpregset;
return NULL;
}
Index: gdb/ppc-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/ppc-tdep.h,v
retrieving revision 1.55
diff -u -p -r1.55 ppc-tdep.h
--- gdb/ppc-tdep.h 23 Aug 2007 18:08:36 -0000 1.55
+++ gdb/ppc-tdep.h 24 Aug 2007 13:08:21 -0000
@@ -56,12 +56,8 @@ CORE_ADDR ppc64_sysv_abi_adjust_breakpoi
CORE_ADDR bpaddr);
int ppc_linux_memory_remove_breakpoint (struct bp_target_info *bp_tgt);
struct link_map_offsets *ppc_linux_svr4_fetch_link_map_offsets (void);
-void ppc_linux_supply_gregset (struct regcache *regcache,
- int regnum, const void *gregs, size_t size,
- int wordsize);
-void ppc_linux_supply_fpregset (const struct regset *regset,
- struct regcache *regcache,
- int regnum, const void *gregs, size_t size);
+const struct regset *ppc_linux_gregset (int);
+const struct regset *ppc_linux_fpregset (void);
enum return_value_convention ppc64_sysv_abi_return_value (struct gdbarch *gdbarch,
struct type *valtype,
@@ -83,6 +79,7 @@ struct ppc_reg_offsets
{
/* General-purpose registers. */
int r0_offset;
+ int gpr_size;
int pc_offset;
int ps_offset;
int cr_offset;
Index: gdb/ppcnbsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppcnbsd-tdep.c,v
retrieving revision 1.33
diff -u -p -r1.33 ppcnbsd-tdep.c
--- gdb/ppcnbsd-tdep.c 23 Aug 2007 18:08:36 -0000 1.33
+++ gdb/ppcnbsd-tdep.c 24 Aug 2007 13:08:21 -0000
@@ -213,6 +213,7 @@ _initialize_ppcnbsd_tdep (void)
{
/* General-purpose registers. */
ppcnbsd_reg_offsets.r0_offset = 0;
+ ppcnbsd_reg_offsets.gpr_size = 4;
ppcnbsd_reg_offsets.lr_offset = 128;
ppcnbsd_reg_offsets.cr_offset = 132;
ppcnbsd_reg_offsets.xer_offset = 136;
Index: gdb/ppcobsd-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppcobsd-tdep.c,v
retrieving revision 1.17
diff -u -p -r1.17 ppcobsd-tdep.c
--- gdb/ppcobsd-tdep.c 23 Aug 2007 18:08:36 -0000 1.17
+++ gdb/ppcobsd-tdep.c 24 Aug 2007 13:08:21 -0000
@@ -51,18 +51,6 @@ ppcobsd_supply_gregset (const struct reg
struct regcache *regcache, int regnum,
const void *gregs, size_t len)
{
- /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
- point registers. Traditionally, GDB's register set has still
- listed the floating point registers for such machines, so this
- code is harmless. However, the new E500 port actually omits the
- floating point registers entirely from the register set --- they
- don't even have register numbers assigned to them.
-
- It's not clear to me how best to update this code, so this assert
- will alert the first person to encounter the OpenBSD/E500
- combination to the problem. */
- gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
-
ppc_supply_gregset (regset, regcache, regnum, gregs, len);
ppc_supply_fpregset (regset, regcache, regnum, gregs, len);
}
@@ -77,18 +65,6 @@ ppcobsd_collect_gregset (const struct re
const struct regcache *regcache, int regnum,
void *gregs, size_t len)
{
- /* FIXME: jimb/2004-05-05: Some PPC variants don't have floating
- point registers. Traditionally, GDB's register set has still
- listed the floating point registers for such machines, so this
- code is harmless. However, the new E500 port actually omits the
- floating point registers entirely from the register set --- they
- don't even have register numbers assigned to them.
-
- It's not clear to me how best to update this code, so this assert
- will alert the first person to encounter the OpenBSD/E500
- combination to the problem. */
- gdb_assert (ppc_floating_point_unit_p (current_gdbarch));
-
ppc_collect_gregset (regset, regcache, regnum, gregs, len);
ppc_collect_fpregset (regset, regcache, regnum, gregs, len);
}
@@ -331,6 +307,7 @@ _initialize_ppcobsd_tdep (void)
{
/* General-purpose registers. */
ppcobsd_reg_offsets.r0_offset = 0;
+ ppcobsd_reg_offsets.gpr_size = 4;
ppcobsd_reg_offsets.pc_offset = 384;
ppcobsd_reg_offsets.ps_offset = 388;
ppcobsd_reg_offsets.cr_offset = 392;
Index: gdb/rs6000-aix-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-aix-tdep.c,v
retrieving revision 1.5
diff -u -p -r1.5 rs6000-aix-tdep.c
--- gdb/rs6000-aix-tdep.c 23 Aug 2007 18:08:37 -0000 1.5
+++ gdb/rs6000-aix-tdep.c 24 Aug 2007 13:08:21 -0000
@@ -85,9 +85,7 @@ rs6000_aix_supply_regset (const struct r
const void *gregs, size_t len)
{
ppc_supply_gregset (regset, regcache, regnum, gregs, len);
-
- if (ppc_floating_point_unit_p (get_regcache_arch (regcache)))
- ppc_supply_fpregset (regset, regcache, regnum, gregs, len);
+ ppc_supply_fpregset (regset, regcache, regnum, gregs, len);
}
/* Collect register REGNUM in the general-purpose register set
@@ -101,9 +99,7 @@ rs6000_aix_collect_regset (const struct
void *gregs, size_t len)
{
ppc_collect_gregset (regset, regcache, regnum, gregs, len);
-
- if (ppc_floating_point_unit_p (get_regcache_arch (regcache)))
- ppc_collect_fpregset (regset, regcache, regnum, gregs, len);
+ ppc_collect_fpregset (regset, regcache, regnum, gregs, len);
}
/* AIX register set. */
Index: gdb/rs6000-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/rs6000-tdep.c,v
retrieving revision 1.287
diff -u -p -r1.287 rs6000-tdep.c
--- gdb/rs6000-tdep.c 23 Aug 2007 18:08:37 -0000 1.287
+++ gdb/rs6000-tdep.c 24 Aug 2007 13:08:24 -0000
@@ -302,22 +302,106 @@ rs6000_register_sim_regno (int reg)
/* Register set support functions. */
+/* REGS + OFFSET contains register REGNUM in a field REGSIZE wide.
+ Write the register to REGCACHE. */
+
static void
ppc_supply_reg (struct regcache *regcache, int regnum,
- const gdb_byte *regs, size_t offset)
+ const gdb_byte *regs, size_t offset, int regsize)
{
if (regnum != -1 && offset != -1)
- regcache_raw_supply (regcache, regnum, regs + offset);
+ {
+ if (regsize > 4)
+ {
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ int gdb_regsize = register_size (gdbarch, regnum);
+ if (gdb_regsize < regsize
+ && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ offset += regsize - gdb_regsize;
+ }
+ regcache_raw_supply (regcache, regnum, regs + offset);
+ }
}
+/* Read register REGNUM from REGCACHE and store to REGS + OFFSET
+ in a field REGSIZE wide. Zero pad as necessary. */
+
static void
ppc_collect_reg (const struct regcache *regcache, int regnum,
- gdb_byte *regs, size_t offset)
+ gdb_byte *regs, size_t offset, int regsize)
{
if (regnum != -1 && offset != -1)
- regcache_raw_collect (regcache, regnum, regs + offset);
+ {
+ if (regsize > 4)
+ {
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ int gdb_regsize = register_size (gdbarch, regnum);
+ if (gdb_regsize < regsize)
+ {
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ {
+ memset (regs + offset, 0, regsize - gdb_regsize);
+ offset += regsize - gdb_regsize;
+ }
+ else
+ memset (regs + offset + regsize - gdb_regsize, 0,
+ regsize - gdb_regsize);
+ }
+ }
+ regcache_raw_collect (regcache, regnum, regs + offset);
+ }
}
+static int
+ppc_greg_offset (struct gdbarch *gdbarch,
+ struct gdbarch_tdep *tdep,
+ const struct ppc_reg_offsets *offsets,
+ int regnum)
+{
+ if (regnum >= tdep->ppc_gp0_regnum
+ && regnum < tdep->ppc_gp0_regnum + ppc_num_gprs)
+ return (offsets->r0_offset
+ + (regnum - tdep->ppc_gp0_regnum) * offsets->gpr_size);
+
+ if (regnum == gdbarch_pc_regnum (gdbarch))
+ return offsets->pc_offset;
+
+ if (regnum == tdep->ppc_ps_regnum)
+ return offsets->ps_offset;
+
+ if (regnum == tdep->ppc_cr_regnum)
+ return offsets->cr_offset;
+
+ if (regnum == tdep->ppc_lr_regnum)
+ return offsets->lr_offset;
+
+ if (regnum == tdep->ppc_ctr_regnum)
+ return offsets->ctr_offset;
+
+ if (regnum == tdep->ppc_xer_regnum)
+ return offsets->xer_offset;
+
+ if (regnum == tdep->ppc_mq_regnum)
+ return offsets->mq_offset;
+
+ return -1;
+}
+
+static int
+ppc_fpreg_offset (struct gdbarch_tdep *tdep,
+ const struct ppc_reg_offsets *offsets,
+ int regnum)
+{
+ if (regnum >= tdep->ppc_fp0_regnum
+ && regnum < tdep->ppc_fp0_regnum + ppc_num_fprs)
+ return offsets->f0_offset + (regnum - tdep->ppc_fp0_regnum) * 8;
+
+ if (regnum == tdep->ppc_fpscr_regnum)
+ return offsets->fpscr_offset;
+
+ return -1;
+}
+
/* Supply register REGNUM in the general-purpose register set REGSET
from the buffer specified by GREGS and LEN to register cache
REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
@@ -330,36 +414,36 @@ ppc_supply_gregset (const struct regset
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
const struct ppc_reg_offsets *offsets = regset->descr;
size_t offset;
- int i;
+ int gpr_size = offsets->gpr_size;
+
+ if (regnum == -1)
+ {
+ int i;
+
+ for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset;
+ i < tdep->ppc_gp0_regnum + ppc_num_gprs;
+ i++, offset += gpr_size)
+ ppc_supply_reg (regcache, i, gregs, offset, gpr_size);
+
+ ppc_supply_reg (regcache, gdbarch_pc_regnum (gdbarch),
+ gregs, offsets->pc_offset, gpr_size);
+ ppc_supply_reg (regcache, tdep->ppc_ps_regnum,
+ gregs, offsets->ps_offset, gpr_size);
+ ppc_supply_reg (regcache, tdep->ppc_cr_regnum,
+ gregs, offsets->cr_offset, gpr_size);
+ ppc_supply_reg (regcache, tdep->ppc_lr_regnum,
+ gregs, offsets->lr_offset, gpr_size);
+ ppc_supply_reg (regcache, tdep->ppc_ctr_regnum,
+ gregs, offsets->ctr_offset, gpr_size);
+ ppc_supply_reg (regcache, tdep->ppc_xer_regnum,
+ gregs, offsets->xer_offset, gpr_size);
+ ppc_supply_reg (regcache, tdep->ppc_mq_regnum,
+ gregs, offsets->mq_offset, gpr_size);
+ return;
+ }
- for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset;
- i < tdep->ppc_gp0_regnum + ppc_num_gprs;
- i++, offset += 4)
- {
- if (regnum == -1 || regnum == i)
- ppc_supply_reg (regcache, i, gregs, offset);
- }
-
- if (regnum == -1 || regnum == gdbarch_pc_regnum (current_gdbarch))
- ppc_supply_reg (regcache, gdbarch_pc_regnum (current_gdbarch),
- gregs, offsets->pc_offset);
- if (regnum == -1 || regnum == tdep->ppc_ps_regnum)
- ppc_supply_reg (regcache, tdep->ppc_ps_regnum,
- gregs, offsets->ps_offset);
- if (regnum == -1 || regnum == tdep->ppc_cr_regnum)
- ppc_supply_reg (regcache, tdep->ppc_cr_regnum,
- gregs, offsets->cr_offset);
- if (regnum == -1 || regnum == tdep->ppc_lr_regnum)
- ppc_supply_reg (regcache, tdep->ppc_lr_regnum,
- gregs, offsets->lr_offset);
- if (regnum == -1 || regnum == tdep->ppc_ctr_regnum)
- ppc_supply_reg (regcache, tdep->ppc_ctr_regnum,
- gregs, offsets->ctr_offset);
- if (regnum == -1 || regnum == tdep->ppc_xer_regnum)
- ppc_supply_reg (regcache, tdep->ppc_xer_regnum,
- gregs, offsets->cr_offset);
- if (regnum == -1 || regnum == tdep->ppc_mq_regnum)
- ppc_supply_reg (regcache, tdep->ppc_mq_regnum, gregs, offsets->mq_offset);
+ offset = ppc_greg_offset (gdbarch, tdep, offsets, regnum);
+ ppc_supply_reg (regcache, regnum, gregs, offset, gpr_size);
}
/* Supply register REGNUM in the floating-point register set REGSET
@@ -371,29 +455,36 @@ ppc_supply_fpregset (const struct regset
int regnum, const void *fpregs, size_t len)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- const struct ppc_reg_offsets *offsets = regset->descr;
+ struct gdbarch_tdep *tdep;
+ const struct ppc_reg_offsets *offsets;
size_t offset;
- int i;
- gdb_assert (ppc_floating_point_unit_p (gdbarch));
+ if (!ppc_floating_point_unit_p (gdbarch))
+ return;
- offset = offsets->f0_offset;
- for (i = tdep->ppc_fp0_regnum;
- i < tdep->ppc_fp0_regnum + ppc_num_fprs;
- i++, offset += 8)
+ tdep = gdbarch_tdep (gdbarch);
+ offsets = regset->descr;
+ if (regnum == -1)
{
- if (regnum == -1 || regnum == i)
- ppc_supply_reg (regcache, i, fpregs, offset);
+ int i;
+
+ for (i = tdep->ppc_fp0_regnum, offset = offsets->f0_offset;
+ i < tdep->ppc_fp0_regnum + ppc_num_fprs;
+ i++, offset += 8)
+ ppc_supply_reg (regcache, i, fpregs, offset, 8);
+
+ ppc_supply_reg (regcache, tdep->ppc_fpscr_regnum,
+ fpregs, offsets->fpscr_offset, offsets->gpr_size);
+ return;
}
- if (regnum == -1 || regnum == tdep->ppc_fpscr_regnum)
- ppc_supply_reg (regcache, tdep->ppc_fpscr_regnum,
- fpregs, offsets->fpscr_offset);
+ offset = ppc_fpreg_offset (tdep, offsets, regnum);
+ ppc_supply_reg (regcache, regnum, fpregs, offset,
+ regnum == tdep->ppc_fpscr_regnum ? offsets->gpr_size : 8);
}
/* Collect register REGNUM in the general-purpose register set
- REGSET. from register cache REGCACHE into the buffer specified by
+ REGSET from register cache REGCACHE into the buffer specified by
GREGS and LEN. If REGNUM is -1, do this for all registers in
REGSET. */
@@ -406,42 +497,40 @@ ppc_collect_gregset (const struct regset
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
const struct ppc_reg_offsets *offsets = regset->descr;
size_t offset;
- int i;
+ int gpr_size = offsets->gpr_size;
+
+ if (regnum == -1)
+ {
+ int i;
+
+ for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset;
+ i < tdep->ppc_gp0_regnum + ppc_num_gprs;
+ i++, offset += gpr_size)
+ ppc_collect_reg (regcache, i, gregs, offset, gpr_size);
+
+ ppc_collect_reg (regcache, gdbarch_pc_regnum (gdbarch),
+ gregs, offsets->pc_offset, gpr_size);
+ ppc_collect_reg (regcache, tdep->ppc_ps_regnum,
+ gregs, offsets->ps_offset, gpr_size);
+ ppc_collect_reg (regcache, tdep->ppc_cr_regnum,
+ gregs, offsets->cr_offset, gpr_size);
+ ppc_collect_reg (regcache, tdep->ppc_lr_regnum,
+ gregs, offsets->lr_offset, gpr_size);
+ ppc_collect_reg (regcache, tdep->ppc_ctr_regnum,
+ gregs, offsets->ctr_offset, gpr_size);
+ ppc_collect_reg (regcache, tdep->ppc_xer_regnum,
+ gregs, offsets->xer_offset, gpr_size);
+ ppc_collect_reg (regcache, tdep->ppc_mq_regnum,
+ gregs, offsets->mq_offset, gpr_size);
+ return;
+ }
- offset = offsets->r0_offset;
- for (i = tdep->ppc_gp0_regnum;
- i < tdep->ppc_gp0_regnum + ppc_num_gprs;
- i++, offset += 4)
- {
- if (regnum == -1 || regnum == i)
- ppc_collect_reg (regcache, i, gregs, offset);
- }
-
- if (regnum == -1 || regnum == gdbarch_pc_regnum (current_gdbarch))
- ppc_collect_reg (regcache, gdbarch_pc_regnum (current_gdbarch),
- gregs, offsets->pc_offset);
- if (regnum == -1 || regnum == tdep->ppc_ps_regnum)
- ppc_collect_reg (regcache, tdep->ppc_ps_regnum,
- gregs, offsets->ps_offset);
- if (regnum == -1 || regnum == tdep->ppc_cr_regnum)
- ppc_collect_reg (regcache, tdep->ppc_cr_regnum,
- gregs, offsets->cr_offset);
- if (regnum == -1 || regnum == tdep->ppc_lr_regnum)
- ppc_collect_reg (regcache, tdep->ppc_lr_regnum,
- gregs, offsets->lr_offset);
- if (regnum == -1 || regnum == tdep->ppc_ctr_regnum)
- ppc_collect_reg (regcache, tdep->ppc_ctr_regnum,
- gregs, offsets->ctr_offset);
- if (regnum == -1 || regnum == tdep->ppc_xer_regnum)
- ppc_collect_reg (regcache, tdep->ppc_xer_regnum,
- gregs, offsets->xer_offset);
- if (regnum == -1 || regnum == tdep->ppc_mq_regnum)
- ppc_collect_reg (regcache, tdep->ppc_mq_regnum,
- gregs, offsets->mq_offset);
+ offset = ppc_greg_offset (gdbarch, tdep, offsets, regnum);
+ ppc_collect_reg (regcache, regnum, gregs, offset, gpr_size);
}
/* Collect register REGNUM in the floating-point register set
- REGSET. from register cache REGCACHE into the buffer specified by
+ REGSET from register cache REGCACHE into the buffer specified by
FPREGS and LEN. If REGNUM is -1, do this for all registers in
REGSET. */
@@ -451,25 +540,32 @@ ppc_collect_fpregset (const struct regse
int regnum, void *fpregs, size_t len)
{
struct gdbarch *gdbarch = get_regcache_arch (regcache);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- const struct ppc_reg_offsets *offsets = regset->descr;
+ struct gdbarch_tdep *tdep;
+ const struct ppc_reg_offsets *offsets;
size_t offset;
- int i;
- gdb_assert (ppc_floating_point_unit_p (gdbarch));
+ if (!ppc_floating_point_unit_p (gdbarch))
+ return;
- offset = offsets->f0_offset;
- for (i = tdep->ppc_fp0_regnum;
- i <= tdep->ppc_fp0_regnum + ppc_num_fprs;
- i++, offset += 8)
+ tdep = gdbarch_tdep (gdbarch);
+ offsets = regset->descr;
+ if (regnum == -1)
{
- if (regnum == -1 || regnum == i)
- ppc_collect_reg (regcache, i, fpregs, offset);
+ int i;
+
+ for (i = tdep->ppc_fp0_regnum, offset = offsets->f0_offset;
+ i < tdep->ppc_fp0_regnum + ppc_num_fprs;
+ i++, offset += 8)
+ ppc_collect_reg (regcache, i, fpregs, offset, 8);
+
+ ppc_collect_reg (regcache, tdep->ppc_fpscr_regnum,
+ fpregs, offsets->fpscr_offset, offsets->gpr_size);
+ return;
}
- if (regnum == -1 || regnum == tdep->ppc_fpscr_regnum)
- ppc_collect_reg (regcache, tdep->ppc_fpscr_regnum,
- fpregs, offsets->fpscr_offset);
+ offset = ppc_fpreg_offset (tdep, offsets, regnum);
+ ppc_collect_reg (regcache, regnum, fpregs, offset,
+ regnum == tdep->ppc_fpscr_regnum ? offsets->gpr_size : 8);
}
--
Alan Modra
Australia Development Lab, IBM
More information about the Gdb-patches
mailing list