/* Target-dependent code for GDB, the GNU debugger.
- Copyright (C) 1986-2021 Free Software Foundation, Inc.
+ Copyright (C) 1986-2022 Free Software Foundation, Inc.
This file is part of GDB.
/* PowerPC-related per-inferior data. */
-struct ppc_inferior_data
-{
- /* This is an optional in case we add more fields to ppc_inferior_data, we
- don't want it instantiated as soon as we get the ppc_inferior_data for an
- inferior. */
- gdb::optional<displaced_step_buffers> disp_step_buf;
-};
-
static inferior_key<ppc_inferior_data> ppc_inferior_data_key;
/* Get the per-inferior PowerPC data for INF. */
-static ppc_inferior_data *
+ppc_inferior_data *
get_ppc_per_inferior (inferior *inf)
{
ppc_inferior_data *per_inf = ppc_inferior_data_key.get (inf);
int
vsx_register_p (struct gdbarch *gdbarch, int regno)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (tdep->ppc_vsr0_regnum < 0)
return 0;
else
int
altivec_register_p (struct gdbarch *gdbarch, int regno)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (tdep->ppc_vr0_regnum < 0 || tdep->ppc_vrsave_regnum < 0)
return 0;
else
int
spe_register_p (struct gdbarch *gdbarch, int regno)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* Is it a reference to EV0 -- EV31, and do we have those? */
if (IS_SPE_PSEUDOREG (tdep, regno))
int
ppc_floating_point_unit_p (struct gdbarch *gdbarch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
return (tdep->ppc_fp0_regnum >= 0
&& tdep->ppc_fpscr_regnum >= 0);
int
ppc_altivec_support_p (struct gdbarch *gdbarch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
return (tdep->ppc_vr0_regnum >= 0
&& tdep->ppc_vrsave_regnum >= 0);
static void
init_sim_regno_table (struct gdbarch *arch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (arch);
int total_regs = gdbarch_num_regs (arch);
int *sim_regno = GDBARCH_OBSTACK_CALLOC (arch, total_regs, int);
int i;
static int
rs6000_register_sim_regno (struct gdbarch *gdbarch, int reg)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int sim_regno;
if (tdep->sim_regno == NULL)
static int
ppc_greg_offset (struct gdbarch *gdbarch,
- struct gdbarch_tdep *tdep,
+ ppc_gdbarch_tdep *tdep,
const struct ppc_reg_offsets *offsets,
int regnum,
int *regsize)
}
static int
-ppc_fpreg_offset (struct gdbarch_tdep *tdep,
+ppc_fpreg_offset (ppc_gdbarch_tdep *tdep,
const struct ppc_reg_offsets *offsets,
int regnum)
{
int regnum, const void *gregs, size_t len)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
const struct ppc_reg_offsets *offsets
= (const struct ppc_reg_offsets *) regset->regmap;
size_t offset;
int regnum, const void *fpregs, size_t len)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep;
const struct ppc_reg_offsets *offsets;
size_t offset;
if (!ppc_floating_point_unit_p (gdbarch))
return;
- tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
offsets = (const struct ppc_reg_offsets *) regset->regmap;
if (regnum == -1)
{
int regnum, void *gregs, size_t len)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
const struct ppc_reg_offsets *offsets
= (const struct ppc_reg_offsets *) regset->regmap;
size_t offset;
int regnum, void *fpregs, size_t len)
{
struct gdbarch *gdbarch = regcache->arch ();
- struct gdbarch_tdep *tdep;
const struct ppc_reg_offsets *offsets;
size_t offset;
if (!ppc_floating_point_unit_p (gdbarch))
return;
- tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
offsets = (const struct ppc_reg_offsets *) regset->regmap;
if (regnum == -1)
{
rs6000_in_function_epilogue_frame_p (struct frame_info *curfrm,
struct gdbarch *gdbarch, CORE_ADDR pc)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
bfd_byte insn_buf[PPC_INSN_SIZE];
CORE_ADDR scan_pc, func_start, func_end, epilogue_start, epilogue_end;
/* Sequence of bytes for breakpoint instruction. */
-constexpr gdb_byte big_breakpoint[] = { 0x7d, 0x82, 0x10, 0x08 };
-constexpr gdb_byte little_breakpoint[] = { 0x08, 0x10, 0x82, 0x7d };
+constexpr gdb_byte big_breakpoint[] = { 0x7f, 0xe0, 0x00, 0x08 };
+constexpr gdb_byte little_breakpoint[] = { 0x08, 0x00, 0xe0, 0x7f };
typedef BP_MANIPULATION_ENDIAN (little_breakpoint, big_breakpoint)
rs6000_breakpoint;
/* Instruction masks for displaced stepping. */
-#define BRANCH_MASK 0xfc000000
+#define OP_MASK 0xfc000000
#define BP_MASK 0xFC0007FE
#define B_INSN 0x48000000
#define BC_INSN 0x40000000
#define ADDPCIS_TARGET_REGISTER 0x03F00000
#define ADDPCIS_INSN_REGSHIFT 21
+#define PNOP_MASK 0xfff3ffff
+#define PNOP_INSN 0x07000000
+#define R_MASK 0x00100000
+#define R_ZERO 0x00000000
+
/* Check if insn is one of the Load And Reserve instructions used for atomic
sequences. */
#define IS_LOAD_AND_RESERVE_INSN(insn) ((insn & LOAD_AND_RESERVE_MASK) == LWARX_INSTRUCTION \
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int insn;
- read_memory (from, buf, len);
+ len = target_read (current_inferior()->top_target(), TARGET_OBJECT_MEMORY, NULL,
+ buf, from, len);
+ if ((ssize_t) len < PPC_INSN_SIZE)
+ memory_error (TARGET_XFER_E_IO, from);
insn = extract_signed_integer (buf, PPC_INSN_SIZE, byte_order);
+ /* Check for PNOP and for prefixed instructions with R=0. Those
+ instructions are safe to displace. Prefixed instructions with R=1
+ will read/write data to/from locations relative to the current PC.
+ We would not be able to fixup after an instruction has written data
+ into a displaced location, so decline to displace those instructions. */
+ if ((insn & OP_MASK) == 1 << 26)
+ {
+ if (((insn & PNOP_MASK) != PNOP_INSN)
+ && ((insn & R_MASK) != R_ZERO))
+ {
+ displaced_debug_printf ("Not displacing prefixed instruction %08x at %s",
+ insn, paddress (gdbarch, from));
+ return NULL;
+ }
+ }
+ else
+ /* Non-prefixed instructions.. */
+ {
+ /* Set the instruction length to 4 to match the actual instruction
+ length. */
+ len = 4;
+ }
+
/* Assume all atomic sequences start with a Load and Reserve instruction. */
if (IS_LOAD_AND_RESERVE_INSN (insn))
{
displaced_debug_printf ("copy %s->%s: %s",
paddress (gdbarch, from), paddress (gdbarch, to),
- displaced_step_dump_bytes (buf, len).c_str ());;
+ displaced_step_dump_bytes (buf, len).c_str ());
/* This is a work around for a problem with g++ 4.8. */
return displaced_step_copy_insn_closure_up (closure.release ());
= (ppc_displaced_step_copy_insn_closure *) closure_;
ULONGEST insn = extract_unsigned_integer (closure->buf.data (),
PPC_INSN_SIZE, byte_order);
- ULONGEST opcode = 0;
+ ULONGEST opcode;
/* Offset for non PC-relative instructions. */
- LONGEST offset = PPC_INSN_SIZE;
+ LONGEST offset;
- opcode = insn & BRANCH_MASK;
+ opcode = insn & OP_MASK;
+
+ /* Set offset to 8 if this is an 8-byte (prefixed) instruction. */
+ if ((opcode) == 1 << 26)
+ offset = 2 * PPC_INSN_SIZE;
+ else
+ offset = PPC_INSN_SIZE;
displaced_debug_printf ("(ppc) fixup (%s, %s)",
paddress (gdbarch, from), paddress (gdbarch, to));
int regnum = (insn & ADDPCIS_TARGET_REGISTER) >> ADDPCIS_INSN_REGSHIFT;
/* Read and update the target value. */
regcache_cooked_read_unsigned (regs, regnum , ¤t_val);
- displaced_debug_printf ("addpcis target regnum %d was 0x%lx now 0x%lx",
- regnum, current_val, current_val + displaced_offset );
+ displaced_debug_printf ("addpcis target regnum %d was %s now %s",
+ regnum, paddress (gdbarch, current_val),
+ paddress (gdbarch, current_val
+ + displaced_offset));
regcache_cooked_write_unsigned (regs, regnum,
current_val + displaced_offset);
/* point the PC back at the non-displaced instruction. */
if (insn & 0x1)
{
/* Link register needs to be set to the next instruction's PC. */
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
regcache_cooked_write_unsigned (regs,
- gdbarch_tdep (gdbarch)->ppc_lr_regnum,
+ tdep->ppc_lr_regnum,
from + PPC_INSN_SIZE);
displaced_debug_printf ("(ppc) adjusted LR to %s",
paddress (gdbarch, from + PPC_INSN_SIZE));
else if ((insn & BP_MASK) == BP_INSN)
regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch), from);
else
- /* Handle any other instructions that do not fit in the categories above. */
- regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch),
- from + offset);
+ {
+ /* Handle any other instructions that do not fit in the categories
+ above. */
+ regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch),
+ from + offset);
+ }
}
/* Implementation of gdbarch_displaced_step_prepare. */
instructions. */
for (insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
{
- loc += PPC_INSN_SIZE;
+ if ((insn & OP_MASK) == 1 << 26)
+ loc += 2 * PPC_INSN_SIZE;
+ else
+ loc += PPC_INSN_SIZE;
insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
/* Assume that there is at most one conditional branch in the atomic
sequence. If a conditional branch is found, put a breakpoint in
its destination address. */
- if ((insn & BRANCH_MASK) == BC_INSN)
+ if ((insn & OP_MASK) == BC_INSN)
{
int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000;
int absolute = insn & 2;
int num_skip_non_prologue_insns = 0;
int r0_contains_arg = 0;
const struct bfd_arch_info *arch_info = gdbarch_bfd_arch_info (gdbarch);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
memset (fdata, 0, sizeof (struct rs6000_framedata));
continue;
}
else if ((op & 0xffff0000) == 0x38210000)
- { /* addi r1,r1,SIMM */
- fdata->frameless = 0;
- fdata->offset += SIGNED_SHORT (op);
- offset = fdata->offset;
- continue;
- }
+ { /* addi r1,r1,SIMM */
+ fdata->frameless = 0;
+ fdata->offset += SIGNED_SHORT (op);
+ offset = fdata->offset;
+ continue;
+ }
/* Load up minimal toc pointer. Do not treat an epilogue restore
of r31 as a minimal TOC load. */
else if (((op >> 22) == 0x20f || /* l r31,... or l r30,... */
/* move parameters from argument registers to local variable
registers */
- }
+ }
else if ((op & 0xfc0007fe) == 0x7c000378 && /* mr(.) Rx,Ry */
(((op >> 21) & 31) >= 3) && /* R3 >= Ry >= R10 */
(((op >> 21) & 31) <= 10) &&
}
continue;
- }
+ }
/* Store gen register S at (r31+r0).
Store param on stack when offset from SP bigger than 4 bytes. */
/* 000100 sssss 11111 00000 01100100000 */
/* Never skip branches. */
break;
+ /* Test based on opcode and mask values of
+ powerpc_opcodes[svc..svcla] in opcodes/ppc-opc.c. */
+ if ((op & 0xffff0000) == 0x44000000)
+ /* Never skip system calls. */
+ break;
+
if (num_skip_non_prologue_insns++ > max_skip_non_prologue_insns)
/* Do not scan too many insns, scanning insns is expensive with
remote targets. */
rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
unsigned int ii, op;
int rel;
static struct type *
rs6000_builtin_type_vec64 (struct gdbarch *gdbarch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (!tdep->ppc_builtin_type_vec64)
{
static struct type *
rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (!tdep->ppc_builtin_type_vec128)
{
static const char *
rs6000_register_name (struct gdbarch *gdbarch, int regno)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* The upper half "registers" have names in the XML description,
but we present only the low GPRs and the full 64-bit registers
static struct type *
rs6000_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* These are the e500 pseudo-registers. */
if (IS_SPE_PSEUDOREG (tdep, regnum))
rs6000_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
struct reggroup *group)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (IS_V_ALIAS_PSEUDOREG (tdep, regnum))
return 0;
rs6000_convert_register_p (struct gdbarch *gdbarch, int regnum,
struct type *type)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
return (tdep->ppc_fp0_regnum >= 0
&& regnum >= tdep->ppc_fp0_regnum
struct regcache *regcache, int ev_reg, void *buffer)
{
struct gdbarch *arch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (arch);
int reg_index;
gdb_byte *byte_buffer = (gdb_byte *) buffer;
enum register_status status;
int ev_reg, gdb_byte *buffer)
{
struct gdbarch *arch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int reg_index;
enum register_status status;
dfp_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
int reg_nr, gdb_byte *buffer)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int reg_index, fp0;
enum register_status status;
dfp_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
int reg_nr, const gdb_byte *buffer)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int reg_index, fp0;
if (IS_DFP_PSEUDOREG (tdep, reg_nr))
readable_regcache *regcache, int reg_nr,
gdb_byte *buffer)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
return regcache->raw_read (tdep->ppc_vr0_regnum
struct regcache *regcache,
int reg_nr, const gdb_byte *buffer)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
regcache->raw_write (tdep->ppc_vr0_regnum
vsx_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
int reg_nr, gdb_byte *buffer)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int reg_index, vr0, fp0, vsr0_upper;
enum register_status status;
vsx_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
int reg_nr, const gdb_byte *buffer)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int reg_index, vr0, fp0, vsr0_upper;
if (IS_VSX_PSEUDOREG (tdep, reg_nr))
efp_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
int reg_nr, gdb_byte *buffer)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int reg_index, vr0;
if (IS_EFP_PSEUDOREG (tdep, reg_nr))
efp_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
int reg_nr, const gdb_byte *buffer)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int reg_index, vr0;
int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
int reg_nr, gdb_byte *buffer)
{
struct gdbarch *regcache_arch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
gdb_assert (regcache_arch == gdbarch);
int reg_nr, const gdb_byte *buffer)
{
struct gdbarch *regcache_arch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
gdb_assert (regcache_arch == gdbarch);
dfp_ax_pseudo_register_collect (struct gdbarch *gdbarch,
struct agent_expr *ax, int reg_nr)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int reg_index, fp0;
if (IS_DFP_PSEUDOREG (tdep, reg_nr))
v_alias_pseudo_register_collect (struct gdbarch *gdbarch,
struct agent_expr *ax, int reg_nr)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
ax_reg_mask (ax, tdep->ppc_vr0_regnum
vsx_ax_pseudo_register_collect (struct gdbarch *gdbarch,
struct agent_expr *ax, int reg_nr)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int reg_index, vr0, fp0, vsr0_upper;
if (IS_VSX_PSEUDOREG (tdep, reg_nr))
efp_ax_pseudo_register_collect (struct gdbarch *gdbarch,
struct agent_expr *ax, int reg_nr)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int reg_index, vr0;
if (IS_EFP_PSEUDOREG (tdep, reg_nr))
rs6000_ax_pseudo_register_collect (struct gdbarch *gdbarch,
struct agent_expr *ax, int reg_nr)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (IS_SPE_PSEUDOREG (tdep, reg_nr))
{
int reg_index = reg_nr - tdep->ppc_ev0_regnum;
struct agent_expr *ax, struct axs_value *value,
CORE_ADDR scope)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
value->type = register_type (gdbarch, tdep->ppc_lr_regnum);
value->kind = axs_lvalue_register;
value->u.reg = tdep->ppc_lr_regnum;
static int
rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (0 <= num && num <= 31)
return tdep->ppc_gp0_regnum + num;
static int
rs6000_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int num)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (0 <= num && num <= 31)
return tdep->ppc_gp0_regnum + num;
{
struct rs6000_frame_cache *cache;
struct gdbarch *gdbarch = get_frame_arch (this_frame);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
struct rs6000_framedata fdata;
int wordsize = tdep->wordsize;
static const struct frame_unwind rs6000_frame_unwind =
{
+ "rs6000 prologue",
NORMAL_FRAME,
default_frame_unwind_stop_reason,
rs6000_frame_this_id,
{
struct rs6000_frame_cache *cache;
struct gdbarch *gdbarch = get_frame_arch (this_frame);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (*this_cache)
return (struct rs6000_frame_cache *) *this_cache;
static const struct frame_unwind rs6000_epilogue_frame_unwind =
{
+ "rs6000 epilogue",
NORMAL_FRAME,
default_frame_unwind_stop_reason,
rs6000_epilogue_frame_this_id, rs6000_epilogue_frame_prev_register,
struct dwarf2_frame_state_reg *reg,
struct frame_info *this_frame)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* PPC32 and PPC64 ABI's are the same regarding volatile and
non-volatile registers. We will use the same code for both. */
Otherwise, it's just a VR register. Record them accordingly. */
static int
-ppc_record_vsr (struct regcache *regcache, struct gdbarch_tdep *tdep, int vsr)
+ppc_record_vsr (struct regcache *regcache, ppc_gdbarch_tdep *tdep, int vsr)
{
if (vsr < 0 || vsr >= 64)
return -1;
ppc_process_record_op4 (struct gdbarch *gdbarch, struct regcache *regcache,
CORE_ADDR addr, uint32_t insn)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int ext = PPC_FIELD (insn, 21, 11);
int vra = PPC_FIELD (insn, 11, 5);
ppc_process_record_op19 (struct gdbarch *gdbarch, struct regcache *regcache,
CORE_ADDR addr, uint32_t insn)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int ext = PPC_EXTOP (insn);
switch (ext & 0x01f)
ppc_process_record_op31 (struct gdbarch *gdbarch, struct regcache *regcache,
CORE_ADDR addr, uint32_t insn)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int ext = PPC_EXTOP (insn);
int tmp, nr, nb, i;
CORE_ADDR at_dcsz, ea = 0;
switch (ext)
{
case 167: /* Store Vector Element Halfword Indexed */
- addr = addr & ~0x1ULL;
+ ea = ea & ~0x1ULL;
break;
case 199: /* Store Vector Element Word Indexed */
- addr = addr & ~0x3ULL;
+ ea = ea & ~0x3ULL;
break;
case 231: /* Store Vector Indexed */
case 487: /* Store Vector Indexed LRU */
- addr = addr & ~0xfULL;
+ ea = ea & ~0xfULL;
break;
}
- record_full_arch_list_add_mem (addr, size);
+ record_full_arch_list_add_mem (ea, size);
return 0;
case 397: /* Store VSX Vector with Length */
ppc_process_record_op59 (struct gdbarch *gdbarch, struct regcache *regcache,
CORE_ADDR addr, uint32_t insn)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int ext = PPC_EXTOP (insn);
switch (ext & 0x1f)
ppc_process_record_op60 (struct gdbarch *gdbarch, struct regcache *regcache,
CORE_ADDR addr, uint32_t insn)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int ext = PPC_EXTOP (insn);
switch (ext >> 2)
ppc_process_record_op61 (struct gdbarch *gdbarch, struct regcache *regcache,
CORE_ADDR addr, uint32_t insn)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
ULONGEST ea = 0;
int size;
ppc_process_record_op63 (struct gdbarch *gdbarch, struct regcache *regcache,
CORE_ADDR addr, uint32_t insn)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int ext = PPC_EXTOP (insn);
int tmp;
ppc_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
CORE_ADDR addr)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
uint32_t insn;
int op6, tmp, i;
}
else
{
- printf_unfiltered (_("no syscall record support\n"));
+ fprintf_unfiltered (gdb_stderr, _("no syscall record support\n"));
return -1;
}
break;
return 0;
}
+/* Used for matching tw, twi, td and tdi instructions for POWER. */
+
+static constexpr uint32_t TX_INSN_MASK = 0xFC0007FF;
+static constexpr uint32_t TW_INSN = 0x7C000008;
+static constexpr uint32_t TD_INSN = 0x7C000088;
+
+static constexpr uint32_t TXI_INSN_MASK = 0xFC000000;
+static constexpr uint32_t TWI_INSN = 0x0C000000;
+static constexpr uint32_t TDI_INSN = 0x08000000;
+
+static inline bool
+is_tw_insn (uint32_t insn)
+{
+ return (insn & TX_INSN_MASK) == TW_INSN;
+}
+
+static inline bool
+is_twi_insn (uint32_t insn)
+{
+ return (insn & TXI_INSN_MASK) == TWI_INSN;
+}
+
+static inline bool
+is_td_insn (uint32_t insn)
+{
+ return (insn & TX_INSN_MASK) == TD_INSN;
+}
+
+static inline bool
+is_tdi_insn (uint32_t insn)
+{
+ return (insn & TXI_INSN_MASK) == TDI_INSN;
+}
+
+/* Implementation of gdbarch_program_breakpoint_here_p for POWER. */
+
+static bool
+rs6000_program_breakpoint_here_p (gdbarch *gdbarch, CORE_ADDR address)
+{
+ gdb_byte target_mem[PPC_INSN_SIZE];
+
+ /* Enable the automatic memory restoration from breakpoints while
+ we read the memory. Otherwise we may find temporary breakpoints, ones
+ inserted by GDB, and flag them as permanent breakpoints. */
+ scoped_restore restore_memory
+ = make_scoped_restore_show_memory_breakpoints (0);
+
+ if (target_read_memory (address, target_mem, PPC_INSN_SIZE) == 0)
+ {
+ uint32_t insn = (uint32_t) extract_unsigned_integer
+ (target_mem, PPC_INSN_SIZE, gdbarch_byte_order_for_code (gdbarch));
+
+ /* Check if INSN is a TW, TWI, TD or TDI instruction. There
+ are multiple choices of such instructions with different registers
+ and / or immediate values but they all cause a break. */
+ if (is_tw_insn (insn) || is_twi_insn (insn) || is_td_insn (insn)
+ || is_tdi_insn (insn))
+ return true;
+ }
+
+ return false;
+}
+
/* Initialize the current architecture based on INFO. If possible, re-use an
architecture from ARCHES, which is a list of architectures already created
during this debugging session.
rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
struct gdbarch *gdbarch;
- struct gdbarch_tdep *tdep;
int wordsize, from_xcoff_exec, from_elf_exec;
enum bfd_architecture arch;
unsigned long mach;
/* Word size in the various PowerPC bfd_arch_info structs isn't
meaningful, because 64-bit CPUs can run in 32-bit mode. So, perform
separate word size check. */
- tdep = gdbarch_tdep (arches->gdbarch);
+ ppc_gdbarch_tdep *tdep
+ = (ppc_gdbarch_tdep *) gdbarch_tdep (arches->gdbarch);
if (tdep && tdep->elf_abi != elf_abi)
continue;
if (tdep && tdep->soft_float != soft_float)
- "set arch" trust blindly
- GDB startup useless but harmless */
- tdep = XCNEW (struct gdbarch_tdep);
+ ppc_gdbarch_tdep *tdep = new ppc_gdbarch_tdep;
tdep->wordsize = wordsize;
tdep->elf_abi = elf_abi;
tdep->soft_float = soft_float;
rs6000_breakpoint::kind_from_pc);
set_gdbarch_sw_breakpoint_from_kind (gdbarch,
rs6000_breakpoint::bp_from_kind);
+ set_gdbarch_program_breakpoint_here_p (gdbarch,
+ rs6000_program_breakpoint_here_p);
/* The value of symbols of type N_SO and N_FUN maybe null when
it shouldn't be. */
set_gdbarch_displaced_step_restore_all_in_ptid
(gdbarch, ppc_displaced_step_restore_all_in_ptid);
- set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE);
+ set_gdbarch_max_insn_length (gdbarch, 2 * PPC_INSN_SIZE);
/* Hook in ABI-specific overrides, if they have been registered. */
info.target_desc = tdesc;
static void
rs6000_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = (ppc_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (tdep == NULL)
return;
struct gdbarch_info info;
/* Update the architecture. */
- gdbarch_info_init (&info);
if (!gdbarch_update_p (info))
internal_error (__FILE__, __LINE__, _("could not update architecture"));
}
powerpc_set_vector_abi (const char *args, int from_tty,
struct cmd_list_element *c)
{
- struct gdbarch_info info;
int vector_abi;
for (vector_abi = POWERPC_VEC_AUTO;
powerpc_vector_abi_string);
/* Update the architecture. */
- gdbarch_info_init (&info);
+ gdbarch_info info;
if (!gdbarch_update_p (info))
internal_error (__FILE__, __LINE__, _("could not update architecture"));
}
return ((((CORE_ADDR) insn & 0xfffc) ^ 0x8000) - 0x8000);
}
+CORE_ADDR
+ppc_insn_prefix_dform (unsigned int insn1, unsigned int insn2)
+{
+ /* result is 34-bits */
+ return (CORE_ADDR) ((((insn1 & 0x3ffff) ^ 0x20000) - 0x20000) << 16)
+ | (CORE_ADDR)(insn2 & 0xffff);
+}
+
/* Initialization code. */
void _initialize_rs6000_tdep ();
/* Add root prefix command for all "set powerpc"/"show powerpc"
commands. */
- add_basic_prefix_cmd ("powerpc", no_class,
- _("Various PowerPC-specific commands."),
- &setpowerpccmdlist, "set powerpc ", 0, &setlist);
-
- add_show_prefix_cmd ("powerpc", no_class,
- _("Various PowerPC-specific commands."),
- &showpowerpccmdlist, "show powerpc ", 0, &showlist);
+ add_setshow_prefix_cmd ("powerpc", no_class,
+ _("Various PowerPC-specific commands."),
+ _("Various PowerPC-specific commands."),
+ &setpowerpccmdlist, &showpowerpccmdlist,
+ &setlist, &showlist);
/* Add a command to allow the user to force the ABI. */
add_setshow_auto_boolean_cmd ("soft-float", class_support,