#include "ppc-tdep.h"
#include "ppc64-tdep.h"
#include "ppc-linux-tdep.h"
+#include "arch/ppc-linux-common.h"
+#include "arch/ppc-linux-tdesc.h"
#include "glibc-tdep.h"
#include "trad-frame.h"
#include "frame-unwind.h"
#include "tramp-frame.h"
-#include "observer.h"
+#include "observable.h"
#include "auxv.h"
#include "elf/common.h"
#include "elf/ppc64.h"
}
}
+static void
+ppc_linux_collect_vrregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *buf, size_t len)
+{
+ gdb_byte *vrregs = (gdb_byte *) buf;
+
+ /* Zero-pad the unused bytes in the fields for vscr and vrsave
+ in case they get displayed somewhere (e.g. in core files). */
+ if (regnum == PPC_VSCR_REGNUM || regnum == -1)
+ memset (&vrregs[32 * 16], 0, 16);
+
+ if (regnum == PPC_VRSAVE_REGNUM || regnum == -1)
+ memset (&vrregs[33 * 16], 0, 16);
+
+ regcache_collect_regset (regset, regcache, regnum, buf, len);
+}
+
/* Regset descriptions. */
static const struct ppc_reg_offsets ppc32_linux_reg_offsets =
{
/* Floating-point registers. */
/* .f0_offset = */ 0,
/* .fpscr_offset = */ 256,
- /* .fpscr_size = */ 8,
-
- /* AltiVec registers. */
- /* .vr0_offset = */ 0,
- /* .vscr_offset = */ 512 + 12,
- /* .vrsave_offset = */ 528
+ /* .fpscr_size = */ 8
};
static const struct ppc_reg_offsets ppc64_linux_reg_offsets =
/* Floating-point registers. */
/* .f0_offset = */ 0,
/* .fpscr_offset = */ 256,
- /* .fpscr_size = */ 8,
-
- /* AltiVec registers. */
- /* .vr0_offset = */ 0,
- /* .vscr_offset = */ 512 + 12,
- /* .vrsave_offset = */ 528
+ /* .fpscr_size = */ 8
};
static const struct regset ppc32_linux_gregset = {
ppc_collect_fpregset
};
-static const struct regset ppc32_linux_vrregset = {
- &ppc32_linux_reg_offsets,
- ppc_supply_vrregset,
- ppc_collect_vrregset
+static const struct regcache_map_entry ppc32_le_linux_vrregmap[] =
+ {
+ { 32, PPC_VR0_REGNUM, 16 },
+ { 1, PPC_VSCR_REGNUM, 4 },
+ { 1, REGCACHE_MAP_SKIP, 12 },
+ { 1, PPC_VRSAVE_REGNUM, 4 },
+ { 1, REGCACHE_MAP_SKIP, 12 },
+ { 0 }
+ };
+
+static const struct regcache_map_entry ppc32_be_linux_vrregmap[] =
+ {
+ { 32, PPC_VR0_REGNUM, 16 },
+ { 1, REGCACHE_MAP_SKIP, 12},
+ { 1, PPC_VSCR_REGNUM, 4 },
+ { 1, PPC_VRSAVE_REGNUM, 4 },
+ { 1, REGCACHE_MAP_SKIP, 12 },
+ { 0 }
+ };
+
+static const struct regset ppc32_le_linux_vrregset = {
+ ppc32_le_linux_vrregmap,
+ regcache_supply_regset,
+ ppc_linux_collect_vrregset
+};
+
+static const struct regset ppc32_be_linux_vrregset = {
+ ppc32_be_linux_vrregmap,
+ regcache_supply_regset,
+ ppc_linux_collect_vrregset
};
+static const struct regcache_map_entry ppc32_linux_vsxregmap[] =
+ {
+ { 32, PPC_VSR0_UPPER_REGNUM, 8 },
+ { 0 }
+ };
+
static const struct regset ppc32_linux_vsxregset = {
- &ppc32_linux_reg_offsets,
- ppc_supply_vsxregset,
- ppc_collect_vsxregset
+ ppc32_linux_vsxregmap,
+ regcache_supply_regset,
+ regcache_collect_regset
};
const struct regset *
return &ppc32_linux_fpregset;
}
+const struct regset *
+ppc_linux_vrregset (struct gdbarch *gdbarch)
+{
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ return &ppc32_be_linux_vrregset;
+ else
+ return &ppc32_le_linux_vrregset;
+}
+
+const struct regset *
+ppc_linux_vsxregset (void)
+{
+ return &ppc32_linux_vsxregset;
+}
+
/* Iterate over supported core file register note sections. */
static void
cb (".reg2", 264, &ppc32_linux_fpregset, NULL, cb_data);
if (have_altivec)
- cb (".reg-ppc-vmx", 544, &ppc32_linux_vrregset, "ppc Altivec", cb_data);
+ {
+ const struct regset *vrregset = ppc_linux_vrregset (gdbarch);
+ cb (".reg-ppc-vmx", PPC_LINUX_SIZEOF_VRREGSET, vrregset,
+ "ppc Altivec", cb_data);
+ }
if (have_vsx)
- cb (".reg-ppc-vsx", 256, &ppc32_linux_vsxregset, "POWER7 VSX", cb_data);
+ cb (".reg-ppc-vsx", PPC_LINUX_SIZEOF_VSXREGSET,
+ &ppc32_linux_vsxregset, "POWER7 VSX", cb_data);
}
static void
r0 register. When the function fails, it returns -1. */
static LONGEST
ppc_linux_get_syscall_number (struct gdbarch *gdbarch,
- ptid_t ptid)
+ thread_info *thread)
{
- struct regcache *regcache = get_thread_regcache (ptid);
+ struct regcache *regcache = get_thread_regcache (thread);
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
/* Getting the system call number from the register.
When dealing with PowerPC architecture, this information
is stored at 0th register. */
- regcache_cooked_read (regcache, tdep->ppc_gp0_regnum, buf.data ());
+ regcache->cooked_read (tdep->ppc_gp0_regnum, buf.data ());
return extract_signed_integer (buf.data (), tdep->wordsize, byte_order);
}
struct target_ops *target,
bfd *abfd)
{
+ struct ppc_linux_features features = ppc_linux_no_features;
asection *cell = bfd_sections_find_if (abfd, ppc_linux_spu_section, NULL);
asection *altivec = bfd_get_section_by_name (abfd, ".reg-ppc-vmx");
asection *vsx = bfd_get_section_by_name (abfd, ".reg-ppc-vsx");
asection *section = bfd_get_section_by_name (abfd, ".reg");
+
if (! section)
return NULL;
switch (bfd_section_size (abfd, section))
{
case 48 * 4:
- if (cell)
- return tdesc_powerpc_cell32l;
- else if (vsx)
- return tdesc_powerpc_vsx32l;
- else if (altivec)
- return tdesc_powerpc_altivec32l;
- else
- return tdesc_powerpc_32l;
-
+ features.wordsize = 4;
+ break;
case 48 * 8:
- if (cell)
- return tdesc_powerpc_cell64l;
- else if (vsx)
- return tdesc_powerpc_vsx64l;
- else if (altivec)
- return tdesc_powerpc_altivec64l;
- else
- return tdesc_powerpc_64l;
-
+ features.wordsize = 8;
+ break;
default:
return NULL;
}
+
+ if (cell)
+ features.cell = true;
+
+ if (altivec)
+ features.altivec = true;
+
+ if (vsx)
+ features.vsx = true;
+
+ CORE_ADDR hwcap;
+
+ if (target_auxv_search (target, AT_HWCAP, &hwcap) != 1)
+ hwcap = 0;
+
+ features.isa205 = ppc_linux_has_isa205 (hwcap);
+
+ return ppc_linux_match_description (features);
}
return 0;
/* Look up cached address of thread-local variable. */
- if (!ptid_equal (spe_context_cache_ptid, inferior_ptid))
+ if (spe_context_cache_ptid != inferior_ptid)
{
- struct target_ops *target = ¤t_target;
+ struct target_ops *target = current_top_target ();
TRY
{
Instead, we have cached the lm_addr value, and use that to
directly call the target's to_get_thread_local_address. */
spe_context_cache_address
- = target->to_get_thread_local_address (target, inferior_ptid,
- spe_context_lm_addr,
- spe_context_offset);
+ = target->get_thread_local_address (inferior_ptid,
+ spe_context_lm_addr,
+ spe_context_offset);
spe_context_cache_ptid = inferior_ptid;
}
struct ppu2spu_cache
{
struct frame_id frame_id;
- struct regcache *regcache;
+ readonly_detached_regcache *regcache;
};
static struct gdbarch *
};
static enum register_status
-ppu2spu_unwind_register (void *src, int regnum, gdb_byte *buf)
+ppu2spu_unwind_register (ppu2spu_data *data, int regnum, gdb_byte *buf)
{
- struct ppu2spu_data *data = (struct ppu2spu_data *) src;
enum bfd_endian byte_order = gdbarch_byte_order (data->gdbarch);
if (regnum >= 0 && regnum < SPU_NUM_GPRS)
return 0;
xsnprintf (annex, sizeof annex, "%d/regs", data.id);
- if (target_read (¤t_target, TARGET_OBJECT_SPU, annex,
+ if (target_read (current_top_target (), TARGET_OBJECT_SPU, annex,
data.gprs, 0, sizeof data.gprs)
== sizeof data.gprs)
{
+ auto cooked_read = [&data] (int regnum, gdb_byte *buf)
+ {
+ return ppu2spu_unwind_register (&data, regnum, buf);
+ };
struct ppu2spu_cache *cache
= FRAME_OBSTACK_CALLOC (1, struct ppu2spu_cache);
- std::unique_ptr<struct regcache> regcache
- (new struct regcache (data.gdbarch));
-
- regcache_save (regcache.get (), ppu2spu_unwind_register, &data);
+ std::unique_ptr<readonly_detached_regcache> regcache
+ (new readonly_detached_regcache (data.gdbarch, cooked_read));
cache->frame_id = frame_id_build (base, func);
cache->regcache = regcache.release ();
ppc_linux_init_abi);
/* Attach to observers to track __spe_current_active_context. */
- observer_attach_inferior_created (ppc_linux_spe_context_inferior_created);
- observer_attach_solib_loaded (ppc_linux_spe_context_solib_loaded);
- observer_attach_solib_unloaded (ppc_linux_spe_context_solib_unloaded);
+ gdb::observers::inferior_created.attach (ppc_linux_spe_context_inferior_created);
+ gdb::observers::solib_loaded.attach (ppc_linux_spe_context_solib_loaded);
+ gdb::observers::solib_unloaded.attach (ppc_linux_spe_context_solib_unloaded);
/* Initialize the Linux target descriptions. */
initialize_tdesc_powerpc_32l ();