From f2db237aa14bae7e5e7a7c4c85e4c2c84b11a30e Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Thu, 30 Aug 2007 13:13:59 +0000 Subject: [PATCH] * 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. (ppc_linux_collect_gregset): New function. (ppc32_linux_reg_offsets, ppc64_linux_reg_offsets): New. (ppc32_linux_gregset, ppc64_linux_gregset): Update to use reg offsets, ppc_linux_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, xr_size, fpscr_size fields. * ppcobsd-tdep.c (ppcobsd_supply_gregset): Delete FIXME and assert. (ppcobsd_collect_gregset): Likewise. (_initialize_ppcnbsd_tdep): Init gpr_size, xr_size, fpscr_size. * ppcnbsd-tdep.c (_initialize_ppcobsd_tdep): Likewise. * ppcobsd-nat.c (_initialize_ppcobsd_nat): Likewise. * rs6000-aix-tdep.c (rs6000_aix32_reg_offsets): Likewise. (rs6000_aix64_reg_offsets): Likewise. (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. --- gdb/ChangeLog | 45 +++++++ gdb/ppc-linux-nat.c | 93 ++++---------- gdb/ppc-linux-tdep.c | 208 +++++++++++++------------------- gdb/ppc-tdep.h | 11 +- gdb/ppcnbsd-tdep.c | 3 + gdb/ppcobsd-nat.c | 3 + gdb/ppcobsd-tdep.c | 27 +---- gdb/rs6000-aix-tdep.c | 14 ++- gdb/rs6000-tdep.c | 273 +++++++++++++++++++++++++++++------------- 9 files changed, 357 insertions(+), 320 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b3604447929..b45ccf48561 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,48 @@ +2007-08-30 Alan Modra + + * 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. + (ppc_linux_collect_gregset): New function. + (ppc32_linux_reg_offsets, ppc64_linux_reg_offsets): New. + (ppc32_linux_gregset, ppc64_linux_gregset): Update to use reg offsets, + ppc_linux_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, xr_size, fpscr_size fields. + * ppcobsd-tdep.c (ppcobsd_supply_gregset): Delete FIXME and assert. + (ppcobsd_collect_gregset): Likewise. + (_initialize_ppcnbsd_tdep): Init gpr_size, xr_size, fpscr_size. + * ppcnbsd-tdep.c (_initialize_ppcobsd_tdep): Likewise. + * ppcobsd-nat.c (_initialize_ppcobsd_nat): Likewise. + * rs6000-aix-tdep.c (rs6000_aix32_reg_offsets): Likewise. + (rs6000_aix64_reg_offsets): Likewise. + (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. + 2007-08-29 Jim Blandy * breakpoint.c (watch_command_1): Remove '#ifdef HPUXHPPA' block; diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c index 60cffc39d65..f0b2abb3e7c 100644 --- a/gdb/ppc-linux-nat.c +++ b/gdb/ppc-linux-nat.c @@ -901,101 +901,48 @@ ppc_linux_store_inferior_registers (struct regcache *regcache, int regno) 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; + const struct regset *regset = ppc_linux_gregset (sizeof (long)); - - /* 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); + if (regno == -1) + memset (gregsetp, 0, sizeof (*gregsetp)); + 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); diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 265c5c15628..324cef74c2a 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -38,51 +38,6 @@ #include "frame-unwind.h" #include "tramp-frame.h" -/* From , 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,102 @@ ppc_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch, return addr; } +/* This wrapper clears areas in the linux gregset not written by + ppc_collect_gregset. */ + static void -right_supply_register (struct regcache *regcache, int wordsize, int regnum, - const bfd_byte *buf) +ppc_linux_collect_gregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *gregs, size_t len) { - regcache_raw_supply (regcache, regnum, - (buf + wordsize - register_size (current_gdbarch, regnum))); + if (regnum == -1) + memset (gregs, 0, len); + ppc_collect_gregset (regset, regcache, regnum, gregs, len); } -/* 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, + /* .xr_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, + /* .fpscr_size = */ 8, + + /* 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, + /* .xr_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, + /* .fpscr_size = */ 8, + + /* AltiVec registers. */ + /* .vr0_offset = */ 0, + /* .vrsave_offset = */ 528, + /* .vscr_offset = */ 512 + 12 + }; -static struct regset ppc32_linux_gregset = { - NULL, ppc32_linux_supply_gregset +static const struct regset ppc32_linux_gregset = { + &ppc32_linux_reg_offsets, + ppc_supply_gregset, + ppc_linux_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 const struct regset ppc64_linux_gregset = { + &ppc64_linux_reg_offsets, + ppc_supply_gregset, + ppc_linux_collect_gregset, + NULL +}; -static struct regset ppc64_linux_gregset = { - NULL, ppc64_linux_supply_gregset +static const struct regset ppc32_linux_fpregset = { + &ppc32_linux_reg_offsets, + ppc_supply_fpregset, + ppc_collect_fpregset, + NULL }; -void -ppc_linux_supply_fpregset (const struct regset *regset, - struct regcache * regcache, - int regnum, const void *fpset, size_t size) +const struct regset * +ppc_linux_gregset (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 = 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); + 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 +725,7 @@ ppc_linux_regset_from_core_section (struct gdbarch *core_arch, return &ppc64_linux_gregset; } if (strcmp (sect_name, ".reg2") == 0) - return &ppc_linux_fpregset; + return &ppc32_linux_fpregset; return NULL; } diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h index 695ffc8d0ef..3c169734bc4 100644 --- a/gdb/ppc-tdep.h +++ b/gdb/ppc-tdep.h @@ -56,12 +56,8 @@ CORE_ADDR ppc64_sysv_abi_adjust_breakpoint_address (struct gdbarch *gdbarch, 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,8 @@ struct ppc_reg_offsets { /* General-purpose registers. */ int r0_offset; + int gpr_size; /* size for r0-31, pc, ps, lr, ctr. */ + int xr_size; /* size for cr, xer, mq. */ int pc_offset; int ps_offset; int cr_offset; @@ -94,6 +92,7 @@ struct ppc_reg_offsets /* Floating-point registers. */ int f0_offset; int fpscr_offset; + int fpscr_size; /* AltiVec registers. */ int vr0_offset; diff --git a/gdb/ppcnbsd-tdep.c b/gdb/ppcnbsd-tdep.c index 21d44e28058..9921ca0e657 100644 --- a/gdb/ppcnbsd-tdep.c +++ b/gdb/ppcnbsd-tdep.c @@ -213,6 +213,8 @@ _initialize_ppcnbsd_tdep (void) { /* General-purpose registers. */ ppcnbsd_reg_offsets.r0_offset = 0; + ppcnbsd_reg_offsets.gpr_size = 4; + ppcnbsd_reg_offsets.xr_size = 4; ppcnbsd_reg_offsets.lr_offset = 128; ppcnbsd_reg_offsets.cr_offset = 132; ppcnbsd_reg_offsets.xer_offset = 136; @@ -224,6 +226,7 @@ _initialize_ppcnbsd_tdep (void) /* Floating-point registers. */ ppcnbsd_reg_offsets.f0_offset = 0; ppcnbsd_reg_offsets.fpscr_offset = 256; + ppcnbsd_reg_offsets.fpscr_size = 4; /* AltiVec registers. */ ppcnbsd_reg_offsets.vr0_offset = 0; diff --git a/gdb/ppcobsd-nat.c b/gdb/ppcobsd-nat.c index 1195d764f89..35269d73584 100644 --- a/gdb/ppcobsd-nat.c +++ b/gdb/ppcobsd-nat.c @@ -198,6 +198,8 @@ _initialize_ppcobsd_nat (void) /* General-purpose registers. */ ppcobsd_reg_offsets.r0_offset = offsetof (struct reg, gpr); + ppcobsd_reg_offsets.gpr_size = 4; + ppcobsd_reg_offsets.xr_size = 4; ppcobsd_reg_offsets.pc_offset = offsetof (struct reg, pc); ppcobsd_reg_offsets.ps_offset = offsetof (struct reg, ps); ppcobsd_reg_offsets.cr_offset = offsetof (struct reg, cnd); @@ -212,6 +214,7 @@ _initialize_ppcobsd_nat (void) #ifdef PT_GETFPREGS ppcobsd_fpreg_offsets.f0_offset = offsetof (struct fpreg, fpr); ppcobsd_fpreg_offsets.fpscr_offset = offsetof (struct fpreg, fpscr); + ppcobsd_fpreg_offsets.fpscr_size = 4; #endif /* AltiVec registers. */ diff --git a/gdb/ppcobsd-tdep.c b/gdb/ppcobsd-tdep.c index c26c5d12c43..dac9e7bb24e 100644 --- a/gdb/ppcobsd-tdep.c +++ b/gdb/ppcobsd-tdep.c @@ -51,18 +51,6 @@ ppcobsd_supply_gregset (const struct regset *regset, 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 regset *regset, 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,8 @@ _initialize_ppcobsd_tdep (void) { /* General-purpose registers. */ ppcobsd_reg_offsets.r0_offset = 0; + ppcobsd_reg_offsets.gpr_size = 4; + ppcobsd_reg_offsets.xr_size = 4; ppcobsd_reg_offsets.pc_offset = 384; ppcobsd_reg_offsets.ps_offset = 388; ppcobsd_reg_offsets.cr_offset = 392; @@ -354,5 +332,6 @@ _initialize_ppcobsd_tdep (void) /* Floating-point registers. */ ppcobsd_reg_offsets.f0_offset = 0; ppcobsd_reg_offsets.fpscr_offset = 256; + ppcobsd_reg_offsets.fpscr_size = 4; } } diff --git a/gdb/rs6000-aix-tdep.c b/gdb/rs6000-aix-tdep.c index 59dda067338..ea284e91445 100644 --- a/gdb/rs6000-aix-tdep.c +++ b/gdb/rs6000-aix-tdep.c @@ -34,6 +34,8 @@ static struct ppc_reg_offsets rs6000_aix32_reg_offsets = { /* General-purpose registers. */ 208, /* r0_offset */ + 4, /* gpr_size */ + 4, /* xr_size */ 24, /* pc_offset */ 28, /* ps_offset */ 32, /* cr_offset */ @@ -45,6 +47,7 @@ static struct ppc_reg_offsets rs6000_aix32_reg_offsets = /* Floating-point registers. */ 336, /* f0_offset */ 56, /* fpscr_offset */ + 4, /* fpscr_size */ /* AltiVec registers. */ -1, /* vr0_offset */ @@ -56,6 +59,8 @@ static struct ppc_reg_offsets rs6000_aix64_reg_offsets = { /* General-purpose registers. */ 0, /* r0_offset */ + 8, /* gpr_size */ + 4, /* xr_size */ 264, /* pc_offset */ 256, /* ps_offset */ 288, /* cr_offset */ @@ -67,6 +72,7 @@ static struct ppc_reg_offsets rs6000_aix64_reg_offsets = /* Floating-point registers. */ 312, /* f0_offset */ 296, /* fpscr_offset */ + 4, /* fpscr_size */ /* AltiVec registers. */ -1, /* vr0_offset */ @@ -85,9 +91,7 @@ rs6000_aix_supply_regset (const struct regset *regset, 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 +105,7 @@ rs6000_aix_collect_regset (const struct regset *regset, 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. */ diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index f6afac9134e..352843471c7 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -302,22 +302,109 @@ 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, + int *regsize) +{ + *regsize = offsets->gpr_size; + 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_lr_regnum) + return offsets->lr_offset; + + if (regnum == tdep->ppc_ctr_regnum) + return offsets->ctr_offset; + + *regsize = offsets->xr_size; + if (regnum == tdep->ppc_cr_regnum) + return offsets->cr_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 +417,37 @@ ppc_supply_gregset (const struct regset *regset, struct regcache *regcache, struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); const struct ppc_reg_offsets *offsets = regset->descr; size_t offset; - int i; + int regsize; - for (i = tdep->ppc_gp0_regnum, offset = offsets->r0_offset; - i < tdep->ppc_gp0_regnum + ppc_num_gprs; - i++, offset += 4) + if (regnum == -1) { - if (regnum == -1 || regnum == i) - ppc_supply_reg (regcache, i, gregs, offset); + int i; + int gpr_size = offsets->gpr_size; + + 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_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_cr_regnum, + gregs, offsets->cr_offset, offsets->xr_size); + ppc_supply_reg (regcache, tdep->ppc_xer_regnum, + gregs, offsets->xer_offset, offsets->xr_size); + ppc_supply_reg (regcache, tdep->ppc_mq_regnum, + gregs, offsets->mq_offset, offsets->xr_size); + return; } - 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, ®size); + ppc_supply_reg (regcache, regnum, gregs, offset, regsize); } /* Supply register REGNUM in the floating-point register set REGSET @@ -371,29 +459,36 @@ ppc_supply_fpregset (const struct regset *regset, struct regcache *regcache, 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->fpscr_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->fpscr_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 +501,41 @@ ppc_collect_gregset (const struct regset *regset, struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); const struct ppc_reg_offsets *offsets = regset->descr; size_t offset; - int i; + int regsize; - offset = offsets->r0_offset; - for (i = tdep->ppc_gp0_regnum; - i < tdep->ppc_gp0_regnum + ppc_num_gprs; - i++, offset += 4) + if (regnum == -1) { - if (regnum == -1 || regnum == i) - ppc_collect_reg (regcache, i, gregs, offset); + int i; + int gpr_size = offsets->gpr_size; + + 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_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_cr_regnum, + gregs, offsets->cr_offset, offsets->xr_size); + ppc_collect_reg (regcache, tdep->ppc_xer_regnum, + gregs, offsets->xer_offset, offsets->xr_size); + ppc_collect_reg (regcache, tdep->ppc_mq_regnum, + gregs, offsets->mq_offset, offsets->xr_size); + return; } - 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, ®size); + ppc_collect_reg (regcache, regnum, gregs, offset, regsize); } /* 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 +545,32 @@ ppc_collect_fpregset (const struct regset *regset, 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->fpscr_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->fpscr_size : 8); } -- 2.30.2