/* Target-dependent code for GDB, the GNU debugger.
- Copyright (C) 1986-2018 Free Software Foundation, Inc.
+ Copyright (C) 1986-2023 Free Software Foundation, Inc.
This file is part of GDB.
#include "osabi.h"
#include "infcall.h"
#include "sim-regno.h"
-#include "gdb/sim-ppc.h"
+#include "sim/sim-ppc.h"
#include "reggroups.h"
-#include "dwarf2-frame.h"
+#include "dwarf2/frame.h"
#include "target-descriptions.h"
#include "user-regs.h"
#include "record-full.h"
&& (regnum) >= (tdep)->ppc_dl0_regnum \
&& (regnum) < (tdep)->ppc_dl0_regnum + 16)
+/* Determine if regnum is a "vX" alias for the raw "vrX" vector
+ registers. */
+#define IS_V_ALIAS_PSEUDOREG(tdep, regnum) (\
+ (tdep)->ppc_v0_alias_regnum >= 0 \
+ && (regnum) >= (tdep)->ppc_v0_alias_regnum \
+ && (regnum) < (tdep)->ppc_v0_alias_regnum + ppc_num_vrs)
+
/* Determine if regnum is a POWER7 VSX register. */
#define IS_VSX_PSEUDOREG(tdep, regnum) ((tdep)->ppc_vsr0_regnum >= 0 \
&& (regnum) >= (tdep)->ppc_vsr0_regnum \
&& (regnum) >= (tdep)->ppc_efpr0_regnum \
&& (regnum) < (tdep)->ppc_efpr0_regnum + ppc_num_efprs)
+/* Determine if regnum is a checkpointed decimal float
+ pseudo-register. */
+#define IS_CDFP_PSEUDOREG(tdep, regnum) ((tdep)->ppc_cdl0_regnum >= 0 \
+ && (regnum) >= (tdep)->ppc_cdl0_regnum \
+ && (regnum) < (tdep)->ppc_cdl0_regnum + 16)
+
+/* Determine if regnum is a Checkpointed POWER7 VSX register. */
+#define IS_CVSX_PSEUDOREG(tdep, regnum) ((tdep)->ppc_cvsr0_regnum >= 0 \
+ && (regnum) >= (tdep)->ppc_cvsr0_regnum \
+ && (regnum) < (tdep)->ppc_cvsr0_regnum + ppc_num_vsrs)
+
+/* Determine if regnum is a Checkpointed POWER7 Extended FP register. */
+#define IS_CEFP_PSEUDOREG(tdep, regnum) ((tdep)->ppc_cefpr0_regnum >= 0 \
+ && (regnum) >= (tdep)->ppc_cefpr0_regnum \
+ && (regnum) < (tdep)->ppc_cefpr0_regnum + ppc_num_efprs)
+
/* Holds the current set of options to be passed to the disassembler. */
static char *powerpc_disassembler_options;
static enum powerpc_vector_abi powerpc_vector_abi_global = POWERPC_VEC_AUTO;
static const char *powerpc_vector_abi_string = "auto";
+/* PowerPC-related per-inferior data. */
+
+static const registry<inferior>::key<ppc_inferior_data> ppc_inferior_data_key;
+
+/* Get the per-inferior PowerPC data for INF. */
+
+ppc_inferior_data *
+get_ppc_per_inferior (inferior *inf)
+{
+ ppc_inferior_data *per_inf = ppc_inferior_data_key.get (inf);
+
+ if (per_inf == nullptr)
+ per_inf = ppc_inferior_data_key.emplace (inf);
+
+ return per_inf;
+}
+
/* To be used by skip_prologue. */
struct rs6000_framedata
int
vsx_register_p (struct gdbarch *gdbarch, int regno)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_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 = gdbarch_tdep<ppc_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 = gdbarch_tdep<ppc_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 = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
return (tdep->ppc_fp0_regnum >= 0
- && tdep->ppc_fpscr_regnum >= 0);
+ && tdep->ppc_fpscr_regnum >= 0);
}
/* Return non-zero if the architecture described by GDBARCH has
int
ppc_altivec_support_p (struct gdbarch *gdbarch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
return (tdep->ppc_vr0_regnum >= 0
- && tdep->ppc_vrsave_regnum >= 0);
+ && tdep->ppc_vrsave_regnum >= 0);
}
/* Check that TABLE[GDB_REGNO] is not already initialized, and then
static void
init_sim_regno_table (struct gdbarch *arch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (arch);
int total_regs = gdbarch_num_regs (arch);
int *sim_regno = GDBARCH_OBSTACK_CALLOC (arch, total_regs, int);
int i;
if (tdep->ppc_fp0_regnum >= 0)
for (i = 0; i < ppc_num_fprs; i++)
set_sim_regno (sim_regno,
- tdep->ppc_fp0_regnum + i,
- sim_ppc_f0_regnum + i);
+ tdep->ppc_fp0_regnum + i,
+ sim_ppc_f0_regnum + i);
if (tdep->ppc_fpscr_regnum >= 0)
set_sim_regno (sim_regno, tdep->ppc_fpscr_regnum, sim_ppc_fpscr_regnum);
if (tdep->ppc_vr0_regnum >= 0)
{
for (i = 0; i < ppc_num_vrs; i++)
- set_sim_regno (sim_regno,
- tdep->ppc_vr0_regnum + i,
- sim_ppc_vr0_regnum + i);
+ set_sim_regno (sim_regno,
+ tdep->ppc_vr0_regnum + i,
+ sim_ppc_vr0_regnum + i);
/* FIXME: jimb/2004-07-15: when we have tdep->ppc_vscr_regnum,
- we can treat this more like the other cases. */
+ we can treat this more like the other cases. */
set_sim_regno (sim_regno,
- tdep->ppc_vr0_regnum + ppc_num_vrs,
- sim_ppc_vscr_regnum);
+ tdep->ppc_vr0_regnum + ppc_num_vrs,
+ sim_ppc_vscr_regnum);
}
/* vsave is a special-purpose register, so the code below handles it. */
if (tdep->ppc_ev0_upper_regnum >= 0)
for (i = 0; i < ppc_num_gprs; i++)
set_sim_regno (sim_regno,
- tdep->ppc_ev0_upper_regnum + i,
- sim_ppc_rh0_regnum + i);
+ tdep->ppc_ev0_upper_regnum + i,
+ sim_ppc_rh0_regnum + i);
if (tdep->ppc_acc_regnum >= 0)
set_sim_regno (sim_regno, tdep->ppc_acc_regnum, sim_ppc_acc_regnum);
/* spefscr is a special-purpose register, so the code below handles it. */
static int
rs6000_register_sim_regno (struct gdbarch *gdbarch, int reg)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
int sim_regno;
if (tdep->sim_regno == NULL)
init_sim_regno_table (gdbarch);
- gdb_assert (0 <= reg
- && reg <= gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch));
+ gdb_assert (0 <= reg && reg <= gdbarch_num_cooked_regs (gdbarch));
sim_regno = tdep->sim_regno[reg];
if (sim_regno >= 0)
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 = gdbarch_tdep<ppc_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 = gdbarch_tdep<ppc_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 = gdbarch_tdep<ppc_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 = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
offsets = (const struct ppc_reg_offsets *) regset->regmap;
if (regnum == -1)
{
/* Changes the stack pointer. */
/* NOTE: There are many ways to change the value of a given register.
- The ways below are those used when the register is R1, the SP,
- in a funtion's epilogue. */
+ The ways below are those used when the register is R1, the SP,
+ in a funtion's epilogue. */
if (opcode == 31 && subcode == 444 && a == 1)
return 1; /* mr R1,Rn */
1) scan forward from the point of execution:
a) If you find an instruction that modifies the stack pointer
- or transfers control (except a return), execution is not in
- an epilogue, return.
+ or transfers control (except a return), execution is not in
+ an epilogue, return.
b) Stop scanning if you find a return instruction or reach the
- end of the function or reach the hard limit for the size of
- an epilogue.
+ end of the function or reach the hard limit for the size of
+ an epilogue.
2) scan backward from the point of execution:
- a) If you find an instruction that modifies the stack pointer,
- execution *is* in an epilogue, return.
- b) Stop scanning if you reach an instruction that transfers
- control or the beginning of the function or reach the hard
- limit for the size of an epilogue. */
+ a) If you find an instruction that modifies the stack pointer,
+ execution *is* in an epilogue, return.
+ b) Stop scanning if you reach an instruction that transfers
+ control or the beginning of the function or reach the hard
+ limit for the size of an epilogue. */
static int
-rs6000_in_function_epilogue_frame_p (struct frame_info *curfrm,
+rs6000_in_function_epilogue_frame_p (frame_info_ptr curfrm,
struct gdbarch *gdbarch, CORE_ADDR pc)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_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;
for (scan_pc = pc; scan_pc < epilogue_end; scan_pc += PPC_INSN_SIZE)
{
- if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
- return 0;
+ if (!safe_frame_unwind_memory (curfrm, scan_pc,
+ {insn_buf, PPC_INSN_SIZE}))
+ return 0;
insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE, byte_order);
if (insn == 0x4e800020)
- break;
+ break;
/* Assume a bctr is a tail call unless it points strictly within
this function. */
if (insn == 0x4e800420)
break;
}
if (insn_changes_sp_or_jumps (insn))
- return 0;
+ return 0;
}
/* Scan backward until adjustment to stack pointer (R1). */
scan_pc >= epilogue_start;
scan_pc -= PPC_INSN_SIZE)
{
- if (!safe_frame_unwind_memory (curfrm, scan_pc, insn_buf, PPC_INSN_SIZE))
- return 0;
+ if (!safe_frame_unwind_memory (curfrm, scan_pc,
+ {insn_buf, PPC_INSN_SIZE}))
+ return 0;
insn = extract_unsigned_integer (insn_buf, PPC_INSN_SIZE, byte_order);
if (insn_changes_sp_or_jumps (insn))
- return 1;
+ return 1;
}
return 0;
/* Get the ith function argument for the current function. */
static CORE_ADDR
-rs6000_fetch_pointer_argument (struct frame_info *frame, int argi,
+rs6000_fetch_pointer_argument (frame_info_ptr frame, int argi,
struct type *type)
{
return get_frame_register_unsigned (frame, 3 + argi);
/* 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 STHCX_INSTRUCTION 0x7c0005ad
#define STQCX_INSTRUCTION 0x7c00016d
+/* Instruction masks for single-stepping of addpcis/lnia. */
+#define ADDPCIS_INSN 0x4c000004
+#define ADDPCIS_INSN_MASK 0xfc00003e
+#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 \
|| (insn & STORE_CONDITIONAL_MASK) == STHCX_INSTRUCTION \
|| (insn & STORE_CONDITIONAL_MASK) == STQCX_INSTRUCTION)
-typedef buf_displaced_step_closure ppc_displaced_step_closure;
+typedef buf_displaced_step_copy_insn_closure
+ ppc_displaced_step_copy_insn_closure;
/* We can't displaced step atomic sequences. */
-static struct displaced_step_closure *
+static displaced_step_copy_insn_closure_up
ppc_displaced_step_copy_insn (struct gdbarch *gdbarch,
CORE_ADDR from, CORE_ADDR to,
struct regcache *regs)
{
- size_t len = gdbarch_max_insn_length (gdbarch);
- std::unique_ptr<ppc_displaced_step_closure> closure
- (new ppc_displaced_step_closure (len));
+ size_t len = gdbarch_displaced_step_buffer_length (gdbarch);
+ gdb_assert (len > PPC_INSN_SIZE);
+ std::unique_ptr<ppc_displaced_step_copy_insn_closure> closure
+ (new ppc_displaced_step_copy_insn_closure (len));
gdb_byte *buf = closure->buf.data ();
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))
{
- if (debug_displaced)
- {
- fprintf_unfiltered (gdb_stdlog,
- "displaced: can't displaced step "
- "atomic sequence at %s\n",
+ displaced_debug_printf ("can't displaced step atomic sequence at %s",
paddress (gdbarch, from));
- }
return NULL;
}
write_memory (to, buf, len);
- if (debug_displaced)
- {
- fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ",
- paddress (gdbarch, from), paddress (gdbarch, to));
- displaced_step_dump_bytes (gdb_stdlog, buf, len);
- }
+ displaced_debug_printf ("copy %s->%s: %s",
+ paddress (gdbarch, from), paddress (gdbarch, to),
+ bytes_to_string (buf, len).c_str ());
- return closure.release ();
+ /* This is a work around for a problem with g++ 4.8. */
+ return displaced_step_copy_insn_closure_up (closure.release ());
}
/* Fix up the state of registers and memory after having single-stepped
a displaced instruction. */
static void
ppc_displaced_step_fixup (struct gdbarch *gdbarch,
- struct displaced_step_closure *closure_,
+ struct displaced_step_copy_insn_closure *closure_,
CORE_ADDR from, CORE_ADDR to,
- struct regcache *regs)
+ struct regcache *regs, bool completed_p)
{
+ /* If the displaced instruction didn't complete successfully then all we
+ need to do is restore the program counter. */
+ if (!completed_p)
+ {
+ CORE_ADDR pc = regcache_read_pc (regs);
+ pc = from + (pc - to);
+ regcache_write_pc (regs, pc);
+ return;
+ }
+
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
/* Our closure is a copy of the instruction. */
- ppc_displaced_step_closure *closure = (ppc_displaced_step_closure *) closure_;
+ ppc_displaced_step_copy_insn_closure *closure
+ = (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;
- if (debug_displaced)
- fprintf_unfiltered (gdb_stdlog,
- "displaced: (ppc) fixup (%s, %s)\n",
- paddress (gdbarch, from), paddress (gdbarch, to));
+ /* 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));
+ /* Handle the addpcis/lnia instruction. */
+ if ((insn & ADDPCIS_INSN_MASK) == ADDPCIS_INSN)
+ {
+ LONGEST displaced_offset;
+ ULONGEST current_val;
+ /* Measure the displacement. */
+ displaced_offset = from - to;
+ /* Identify the target register that was updated by the instruction. */
+ 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 %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. */
+ regcache_cooked_write_unsigned (regs, gdbarch_pc_regnum (gdbarch),
+ from + offset);
+ }
/* Handle PC-relative branch instructions. */
- if (opcode == B_INSN || opcode == BC_INSN || opcode == BXL_INSN)
+ else if (opcode == B_INSN || opcode == BC_INSN || opcode == BXL_INSN)
{
ULONGEST current_pc;
if (!(insn & 0x2))
{
/* PC-relative addressing is being used in the branch. */
- if (debug_displaced)
- fprintf_unfiltered
- (gdb_stdlog,
- "displaced: (ppc) branch instruction: %s\n"
- "displaced: (ppc) adjusted PC from %s to %s\n",
- paddress (gdbarch, insn), paddress (gdbarch, current_pc),
- paddress (gdbarch, from + offset));
+ displaced_debug_printf ("(ppc) branch instruction: %s",
+ paddress (gdbarch, insn));
+ displaced_debug_printf ("(ppc) adjusted PC from %s to %s",
+ paddress (gdbarch, current_pc),
+ paddress (gdbarch, from + offset));
regcache_cooked_write_unsigned (regs,
gdbarch_pc_regnum (gdbarch),
if (insn & 0x1)
{
/* Link register needs to be set to the next instruction's PC. */
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
regcache_cooked_write_unsigned (regs,
- gdbarch_tdep (gdbarch)->ppc_lr_regnum,
+ tdep->ppc_lr_regnum,
from + PPC_INSN_SIZE);
- if (debug_displaced)
- fprintf_unfiltered (gdb_stdlog,
- "displaced: (ppc) adjusted LR to %s\n",
- paddress (gdbarch, 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. */
+
+static displaced_step_prepare_status
+ppc_displaced_step_prepare (gdbarch *arch, thread_info *thread,
+ CORE_ADDR &displaced_pc)
+{
+ ppc_inferior_data *per_inferior = get_ppc_per_inferior (thread->inf);
+
+ if (!per_inferior->disp_step_buf.has_value ())
+ {
+ /* Figure out where the displaced step buffer is. */
+ CORE_ADDR disp_step_buf_addr
+ = displaced_step_at_entry_point (thread->inf->gdbarch);
+
+ per_inferior->disp_step_buf.emplace (disp_step_buf_addr);
+ }
+
+ return per_inferior->disp_step_buf->prepare (thread, displaced_pc);
+}
+
+/* Implementation of gdbarch_displaced_step_finish. */
+
+static displaced_step_finish_status
+ppc_displaced_step_finish (gdbarch *arch, thread_info *thread,
+ const target_waitstatus &status)
+{
+ ppc_inferior_data *per_inferior = get_ppc_per_inferior (thread->inf);
+
+ gdb_assert (per_inferior->disp_step_buf.has_value ());
+
+ return per_inferior->disp_step_buf->finish (arch, thread, status);
+}
+
+/* Implementation of gdbarch_displaced_step_restore_all_in_ptid. */
+
+static void
+ppc_displaced_step_restore_all_in_ptid (inferior *parent_inf, ptid_t ptid)
+{
+ ppc_inferior_data *per_inferior = ppc_inferior_data_key.get (parent_inf);
+
+ if (per_inferior == nullptr
+ || !per_inferior->disp_step_buf.has_value ())
+ return;
+
+ per_inferior->disp_step_buf->restore_in_ptid (ptid);
}
/* Always use hardware single-stepping to execute the
displaced instruction. */
-static int
-ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
- struct displaced_step_closure *closure)
+static bool
+ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch)
{
- return 1;
+ return true;
}
/* Checks for an atomic sequence of instructions beginning with a
struct gdbarch *gdbarch = regcache->arch ();
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR pc = regcache_read_pc (regcache);
- CORE_ADDR breaks[2] = {-1, -1};
+ CORE_ADDR breaks[2] = {CORE_ADDR_MAX, CORE_ADDR_MAX};
CORE_ADDR loc = pc;
CORE_ADDR closing_insn; /* Instruction that closes the atomic sequence. */
int insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
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)
- {
- int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000;
- int absolute = insn & 2;
-
- if (bc_insn_count >= 1)
- return {}; /* More than one conditional branch found, fallback
- to the standard single-step code. */
+ sequence. If a conditional branch is found, put a breakpoint in
+ its destination address. */
+ if ((insn & OP_MASK) == BC_INSN)
+ {
+ int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000;
+ int absolute = insn & 2;
+
+ if (bc_insn_count >= 1)
+ return {}; /* More than one conditional branch found, fallback
+ to the standard single-step code. */
if (absolute)
breaks[1] = immediate;
bc_insn_count++;
last_breakpoint++;
- }
+ }
if (IS_STORE_CONDITIONAL_INSN (insn))
- break;
+ break;
}
/* Assume that the atomic sequence ends with a Store Conditional
const int ry_regno = GET_SRC_REG (op);
if (rx_regno == 0 && ry_regno >= 3 && ry_regno <= 10)
- {
- *r0_contains_arg = 1;
- return 1;
- }
+ {
+ *r0_contains_arg = 1;
+ return 1;
+ }
else
- return 0;
+ return 0;
}
/* Save a General Purpose Register on stack. */
return (rx_regno >= 3 && rx_regno <= 10);
}
-
+
/* Save a General Purpose Register on stack via the Frame Pointer. */
if (framep &&
(op & 0xfc1f0000) == 0xd81f0000)) /* stfd Rx,NUM(r31) */
{
/* Rx: Usually, only r3 - r10 are used for parameter passing.
- However, the compiler sometimes uses r0 to hold an argument. */
+ However, the compiler sometimes uses r0 to hold an argument. */
const int rx_regno = GET_SRC_REG (op);
return ((rx_regno >= 3 && rx_regno <= 10)
- || (rx_regno == 0 && *r0_contains_arg));
+ || (rx_regno == 0 && *r0_contains_arg));
}
if ((op & 0xfc1f0000) == 0xfc010000) /* frsp, fp?,NUM(r1) */
this masking operation is equal to BL_INSTRUCTION, then the opcode in
question is a ``bl'' instruction.
- BL_DISPLACMENT_MASK is anded with the opcode in order to extract
+ BL_DISPLACEMENT_MASK is anded with the opcode in order to extract
the branch displacement. */
#define BL_MASK 0xfc000001
unsigned long op = rs6000_fetch_instruction (gdbarch, pc);
/* First possible sequence: A small number of probes.
- stw 0, -<some immediate>(1)
- [repeat this instruction any (small) number of times]. */
+ stw 0, -<some immediate>(1)
+ [repeat this instruction any (small) number of times]. */
if ((op & 0xffff0000) == 0x90010000)
{
while ((op & 0xffff0000) == 0x90010000)
- {
- pc = pc + 4;
- op = rs6000_fetch_instruction (gdbarch, pc);
- }
+ {
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ }
return pc;
}
/* Second sequence: A probing loop.
- addi 12,1,-<some immediate>
- lis 0,-<some immediate>
- [possibly ori 0,0,<some immediate>]
- add 0,12,0
- cmpw 0,12,0
- beq 0,<disp>
- addi 12,12,-<some immediate>
- stw 0,0(12)
- b <disp>
- [possibly one last probe: stw 0,<some immediate>(12)]. */
+ addi 12,1,-<some immediate>
+ lis 0,-<some immediate>
+ [possibly ori 0,0,<some immediate>]
+ add 0,12,0
+ cmpw 0,12,0
+ beq 0,<disp>
+ addi 12,12,-<some immediate>
+ stw 0,0(12)
+ b <disp>
+ [possibly one last probe: stw 0,<some immediate>(12)]. */
while (1)
{
/* addi 12,1,-<some immediate> */
if ((op & 0xffff0000) != 0x39810000)
- break;
+ break;
/* lis 0,-<some immediate> */
pc = pc + 4;
op = rs6000_fetch_instruction (gdbarch, pc);
if ((op & 0xffff0000) != 0x3c000000)
- break;
+ break;
pc = pc + 4;
op = rs6000_fetch_instruction (gdbarch, pc);
/* [possibly ori 0,0,<some immediate>] */
if ((op & 0xffff0000) == 0x60000000)
- {
- pc = pc + 4;
- op = rs6000_fetch_instruction (gdbarch, pc);
- }
+ {
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ }
/* add 0,12,0 */
if (op != 0x7c0c0214)
- break;
+ break;
/* cmpw 0,12,0 */
pc = pc + 4;
op = rs6000_fetch_instruction (gdbarch, pc);
if (op != 0x7c0c0000)
- break;
+ break;
/* beq 0,<disp> */
pc = pc + 4;
op = rs6000_fetch_instruction (gdbarch, pc);
if ((op & 0xff9f0001) != 0x41820000)
- break;
+ break;
/* addi 12,12,-<some immediate> */
pc = pc + 4;
op = rs6000_fetch_instruction (gdbarch, pc);
if ((op & 0xffff0000) != 0x398c0000)
- break;
+ break;
/* stw 0,0(12) */
pc = pc + 4;
op = rs6000_fetch_instruction (gdbarch, pc);
if (op != 0x900c0000)
- break;
+ break;
/* b <disp> */
pc = pc + 4;
op = rs6000_fetch_instruction (gdbarch, pc);
if ((op & 0xfc000001) != 0x48000000)
- break;
+ break;
/* [possibly one last probe: stw 0,<some immediate>(12)]. */
pc = pc + 4;
op = rs6000_fetch_instruction (gdbarch, pc);
if ((op & 0xffff0000) == 0x900c0000)
- {
- pc = pc + 4;
- op = rs6000_fetch_instruction (gdbarch, pc);
- }
+ {
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ }
/* We found a valid stack-check sequence, return the new PC. */
return pc;
}
- /* Third sequence: No probe; instead, a comparizon between the stack size
+ /* Third sequence: No probe; instead, a comparison between the stack size
limit (saved in a run-time global variable) and the current stack
pointer:
- addi 0,1,-<some immediate>
- lis 12,__gnat_stack_limit@ha
- lwz 12,__gnat_stack_limit@l(12)
- twllt 0,12
+ addi 0,1,-<some immediate>
+ lis 12,__gnat_stack_limit@ha
+ lwz 12,__gnat_stack_limit@l(12)
+ twllt 0,12
or, with a small variant in the case of a bigger stack frame:
- addis 0,1,<some immediate>
- addic 0,0,-<some immediate>
- lis 12,__gnat_stack_limit@ha
- lwz 12,__gnat_stack_limit@l(12)
- twllt 0,12
+ addis 0,1,<some immediate>
+ addic 0,0,-<some immediate>
+ lis 12,__gnat_stack_limit@ha
+ lwz 12,__gnat_stack_limit@l(12)
+ twllt 0,12
*/
while (1)
{
/* addi 0,1,-<some immediate> */
if ((op & 0xffff0000) != 0x38010000)
- {
- /* small stack frame variant not recognized; try the
- big stack frame variant: */
+ {
+ /* small stack frame variant not recognized; try the
+ big stack frame variant: */
- /* addis 0,1,<some immediate> */
- if ((op & 0xffff0000) != 0x3c010000)
- break;
+ /* addis 0,1,<some immediate> */
+ if ((op & 0xffff0000) != 0x3c010000)
+ break;
- /* addic 0,0,-<some immediate> */
- pc = pc + 4;
- op = rs6000_fetch_instruction (gdbarch, pc);
- if ((op & 0xffff0000) != 0x30000000)
- break;
- }
+ /* addic 0,0,-<some immediate> */
+ pc = pc + 4;
+ op = rs6000_fetch_instruction (gdbarch, pc);
+ if ((op & 0xffff0000) != 0x30000000)
+ break;
+ }
/* lis 12,<some immediate> */
pc = pc + 4;
op = rs6000_fetch_instruction (gdbarch, pc);
if ((op & 0xffff0000) != 0x3d800000)
- break;
+ break;
/* lwz 12,<some immediate>(12) */
pc = pc + 4;
op = rs6000_fetch_instruction (gdbarch, pc);
if ((op & 0xffff0000) != 0x818c0000)
- break;
+ break;
/* twllt 0,12 */
pc = pc + 4;
op = rs6000_fetch_instruction (gdbarch, pc);
if ((op & 0xfffffffe) != 0x7c406008)
- break;
+ break;
/* We found a valid stack-check sequence, return the new PC. */
return pc;
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 = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
memset (fdata, 0, sizeof (struct rs6000_framedata));
for (;; pc += 4)
{
/* Sometimes it isn't clear if an instruction is a prologue
- instruction or not. When we encounter one of these ambiguous
+ instruction or not. When we encounter one of these ambiguous
cases, we'll set prev_insn_was_prologue_insn to 0 (false).
Otherwise, we'll assume that it really is a prologue instruction. */
if (prev_insn_was_prologue_insn)
address at runtime, can appear to save more than one link
register vis:
- *INDENT-OFF*
stwu r1,-304(r1)
mflr r3
bl 0xff570d0 (blrl)
stw r31,300(r1)
stw r3,308(r1);
...
- *INDENT-ON*
remember just the first one, but skip over additional
ones. */
if (lr_reg == -1)
lr_reg = (op & 0x03e00000) >> 21;
- if (lr_reg == 0)
- r0_contains_arg = 0;
+ if (lr_reg == 0)
+ r0_contains_arg = 0;
continue;
}
else if ((op & 0xfc1fffff) == 0x7c000026)
{ /* mfcr Rx */
cr_reg = (op & 0x03e00000) >> 21;
- if (cr_reg == 0)
- r0_contains_arg = 0;
+ if (cr_reg == 0)
+ r0_contains_arg = 0;
continue;
}
continue;
}
else if (op == 0x60000000)
- {
+ {
/* nop */
/* Allow nops in the prologue, but do not consider them to
be part of the prologue unless followed by other prologue
{ /* addis 0,0,NUM, used for >= 32k frames */
fdata->offset = (op & 0x0000ffff) << 16;
fdata->frameless = 0;
- r0_contains_arg = 0;
+ r0_contains_arg = 0;
continue;
}
{ /* ori 0,0,NUM, 2nd half of >= 32k frames */
fdata->offset |= (op & 0x0000ffff);
fdata->frameless = 0;
- r0_contains_arg = 0;
+ r0_contains_arg = 0;
continue;
}
/* If the return address has already been saved, we can skip
calls to blrl (for PIC). */
- if (lr_reg != -1 && bl_to_blrl_insn_p (pc, op, byte_order))
+ if (lr_reg != -1 && bl_to_blrl_insn_p (pc, op, byte_order))
{
fdata->used_bl = 1;
continue;
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,... */
continue;
/* move parameters from argument registers to local variable
- registers */
- }
+ registers */
+ }
else if ((op & 0xfc0007fe) == 0x7c000378 && /* mr(.) Rx,Ry */
- (((op >> 21) & 31) >= 3) && /* R3 >= Ry >= R10 */
- (((op >> 21) & 31) <= 10) &&
- ((long) ((op >> 16) & 31)
+ (((op >> 21) & 31) >= 3) && /* R3 >= Ry >= R10 */
+ (((op >> 21) & 31) <= 10) &&
+ ((long) ((op >> 16) & 31)
>= fdata->saved_gpr)) /* Rx: local var reg */
{
continue;
}
/* Move parameters from argument registers to temporary register. */
else if (store_param_on_stack_p (op, framep, &r0_contains_arg))
- {
+ {
continue;
/* Set up frame pointer */
mtspr SPR256 Rn == 011111 nnnnn 0000001000 01110100110 */
else if ((op & 0xfc1fffff) == 0x7c0042a6) /* mfvrsave Rn */
{
- vrsave_reg = GET_SRC_REG (op);
+ vrsave_reg = GET_SRC_REG (op);
continue;
}
else if ((op & 0xfc1fffff) == 0x7c0043a6) /* mtvrsave Rn */
- {
- continue;
- }
+ {
+ continue;
+ }
/* Store the register where vrsave was saved to onto the stack:
- rS is the register where vrsave was stored in a previous
+ rS is the register where vrsave was stored in a previous
instruction. */
/* 100100 sssss 00001 dddddddd dddddddd */
else if ((op & 0xfc1f0000) == 0x90010000) /* stw rS, d(r1) */
- {
- if (vrsave_reg == GET_SRC_REG (op))
+ {
+ if (vrsave_reg == GET_SRC_REG (op))
{
fdata->vrsave_offset = SIGNED_SHORT (op) + offset;
vrsave_reg = -1;
}
- continue;
- }
+ continue;
+ }
/* Compute the new value of vrsave, by modifying the register
- where vrsave was saved to. */
+ where vrsave was saved to. */
else if (((op & 0xfc000000) == 0x64000000) /* oris Ra, Rs, UIMM */
|| ((op & 0xfc000000) == 0x60000000))/* ori Ra, Rs, UIMM */
{
/* 001110 00000 00000 iiii iiii iiii iiii */
/* 001110 01110 00000 iiii iiii iiii iiii */
else if ((op & 0xffff0000) == 0x38000000 /* li r0, SIMM */
- || (op & 0xffff0000) == 0x39c00000) /* li r14, SIMM */
+ || (op & 0xffff0000) == 0x39c00000) /* li r14, SIMM */
{
- if ((op & 0xffff0000) == 0x38000000)
- r0_contains_arg = 0;
+ if ((op & 0xffff0000) == 0x38000000)
+ r0_contains_arg = 0;
li_found_pc = pc;
vr_saved_offset = SIGNED_SHORT (op);
- /* This insn by itself is not part of the prologue, unless
- if part of the pair of insns mentioned above. So do not
- record this insn as part of the prologue yet. */
- prev_insn_was_prologue_insn = 0;
+ /* This insn by itself is not part of the prologue, unless
+ if part of the pair of insns mentioned above. So do not
+ record this insn as part of the prologue yet. */
+ prev_insn_was_prologue_insn = 0;
}
/* Store vector register S at (r31+r0) aligned to 16 bytes. */
/* 011111 sssss 11111 00000 00111001110 */
else if ((op & 0xfc1fffff) == 0x7c1f01ce) /* stvx Vs, R31, R0 */
- {
+ {
if (pc == (li_found_pc + 4))
{
vr_reg = GET_SRC_REG (op);
/* Start BookE related instructions. */
/* Store gen register S at (r31+uimm).
- Any register less than r13 is volatile, so we don't care. */
+ Any register less than r13 is volatile, so we don't care. */
/* 000100 sssss 11111 iiiii 01100100001 */
else if (arch_info->mach == bfd_mach_ppc_e500
&& (op & 0xfc1f07ff) == 0x101f0321) /* evstdd Rs,uimm(R31) */
{
- if ((op & 0x03e00000) >= 0x01a00000) /* Rs >= r13 */
+ if ((op & 0x03e00000) >= 0x01a00000) /* Rs >= r13 */
{
- unsigned int imm;
+ unsigned int imm;
ev_reg = GET_SRC_REG (op);
- imm = (op >> 11) & 0x1f;
+ imm = (op >> 11) & 0x1f;
ev_offset = imm * 8;
/* If this is the first vector reg to be saved, or if
it has a lower number than others previously seen,
fdata->ev_offset = ev_offset + offset;
}
}
- continue;
- }
+ continue;
+ }
/* Store gen register rS at (r1+rB). */
/* 000100 sssss 00001 bbbbb 01100100000 */
else if (arch_info->mach == bfd_mach_ppc_e500
&& (op & 0xffe007ff) == 0x13e00320) /* evstddx RS,R1,Rb */
{
- if (pc == (li_found_pc + 4))
- {
- ev_reg = GET_SRC_REG (op);
+ if (pc == (li_found_pc + 4))
+ {
+ ev_reg = GET_SRC_REG (op);
/* If this is the first vector reg to be saved, or if
- it has a lower number than others previously seen,
- reupdate the frame info. */
- /* We know the contents of rB from the previous instruction. */
+ it has a lower number than others previously seen,
+ reupdate the frame info. */
+ /* We know the contents of rB from the previous instruction. */
if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg)
{
- fdata->saved_ev = ev_reg;
- fdata->ev_offset = vr_saved_offset + offset;
+ fdata->saved_ev = ev_reg;
+ fdata->ev_offset = vr_saved_offset + offset;
}
vr_saved_offset = -1;
ev_reg = -1;
li_found_pc = 0;
- }
- continue;
- }
+ }
+ continue;
+ }
/* Store gen register r31 at (rA+uimm). */
/* 000100 11111 aaaaa iiiii 01100100001 */
else if (arch_info->mach == bfd_mach_ppc_e500
&& (op & 0xffe007ff) == 0x13e00321) /* evstdd R31,Ra,UIMM */
- {
- /* Wwe know that the source register is 31 already, but
- it can't hurt to compute it. */
+ {
+ /* Wwe know that the source register is 31 already, but
+ it can't hurt to compute it. */
ev_reg = GET_SRC_REG (op);
- ev_offset = ((op >> 11) & 0x1f) * 8;
+ ev_offset = ((op >> 11) & 0x1f) * 8;
/* If this is the first vector reg to be saved, or if
it has a lower number than others previously seen,
reupdate the frame info. */
}
continue;
- }
+ }
/* Store gen register S at (r31+r0).
- Store param on stack when offset from SP bigger than 4 bytes. */
+ Store param on stack when offset from SP bigger than 4 bytes. */
/* 000100 sssss 11111 00000 01100100000 */
else if (arch_info->mach == bfd_mach_ppc_e500
&& (op & 0xfc1fffff) == 0x101f0320) /* evstddx Rs,R31,R0 */
{
- if (pc == (li_found_pc + 4))
- {
- if ((op & 0x03e00000) >= 0x01a00000)
+ if (pc == (li_found_pc + 4))
+ {
+ if ((op & 0x03e00000) >= 0x01a00000)
{
ev_reg = GET_SRC_REG (op);
/* If this is the first vector reg to be saved, or if
it has a lower number than others previously seen,
reupdate the frame info. */
- /* We know the contents of r0 from the previous
- instruction. */
+ /* We know the contents of r0 from the previous
+ instruction. */
if (fdata->saved_ev == -1 || fdata->saved_ev > ev_reg)
{
fdata->saved_ev = ev_reg;
vr_saved_offset = -1;
li_found_pc = 0;
continue;
- }
+ }
}
/* End BookE related instructions. */
else
{
- unsigned int all_mask = ~((1U << fdata->saved_gpr) - 1);
-
/* Not a recognized prologue instruction.
Handle optimizer code motions into the prologue by continuing
the search if we have no valid frame yet or if the return
address is not yet saved in the frame. Also skip instructions
if some of the GPRs expected to be saved are not yet saved. */
if (fdata->frameless == 0 && fdata->nosavedpc == 0
- && (fdata->gpr_mask & all_mask) == all_mask)
- break;
+ && fdata->saved_gpr != -1)
+ {
+ unsigned int all_mask = ~((1U << fdata->saved_gpr) - 1);
+
+ if ((fdata->gpr_mask & all_mask) == all_mask)
+ break;
+ }
if (op == 0x4e800020 /* blr */
|| op == 0x4e800420) /* bctr */
/* 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. */
struct bound_minimal_symbol s = lookup_minimal_symbol_by_pc (call_dest);
/* We check for ___eabi (three leading underscores) in addition
- to __eabi in case the GCC option "-fleading-underscore" was
+ to __eabi in case the GCC option "-fleading-underscore" was
used to compile the program. */
if (s.minsym != NULL
- && MSYMBOL_LINKAGE_NAME (s.minsym) != NULL
- && (strcmp (MSYMBOL_LINKAGE_NAME (s.minsym), "__eabi") == 0
- || strcmp (MSYMBOL_LINKAGE_NAME (s.minsym), "___eabi") == 0))
+ && s.minsym->linkage_name () != NULL
+ && (strcmp (s.minsym->linkage_name (), "__eabi") == 0
+ || strcmp (s.minsym->linkage_name (), "___eabi") == 0))
pc += 4;
}
return pc;
code that should be skipped. */
static CORE_ADDR
-rs6000_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
+rs6000_skip_trampoline_code (frame_info_ptr frame, CORE_ADDR pc)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
unsigned int ii, op;
int rel;
msymbol = lookup_minimal_symbol_by_pc (pc);
if (msymbol.minsym
&& rs6000_in_solib_return_trampoline (gdbarch, pc,
- MSYMBOL_LINKAGE_NAME (msymbol.minsym)))
+ msymbol.minsym->linkage_name ()))
{
/* Double-check that the third instruction from PC is relative "b". */
op = read_memory_integer (pc + 8, 4, byte_order);
static struct type *
rs6000_builtin_type_vec64 (struct gdbarch *gdbarch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
if (!tdep->ppc_builtin_type_vec64)
{
append_composite_type_field (t, "v8_int8",
init_vector_type (bt->builtin_int8, 8));
- TYPE_VECTOR (t) = 1;
- TYPE_NAME (t) = "ppc_builtin_type_vec64";
+ t->set_is_vector (true);
+ t->set_name ("ppc_builtin_type_vec64");
tdep->ppc_builtin_type_vec64 = t;
}
static struct type *
rs6000_builtin_type_vec128 (struct gdbarch *gdbarch)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
if (!tdep->ppc_builtin_type_vec128)
{
/* The type we're building is this
type = union __ppc_builtin_type_vec128 {
+ float128_t float128;
uint128_t uint128;
double v2_double[2];
float v4_float[4];
}
*/
+ /* PPC specific type for IEEE 128-bit float field */
+ type_allocator alloc (gdbarch);
+ struct type *t_float128
+ = init_float_type (alloc, 128, "float128_t", floatformats_ieee_quad);
+
struct type *t;
t = arch_composite_type (gdbarch,
"__ppc_builtin_type_vec128", TYPE_CODE_UNION);
+ append_composite_type_field (t, "float128", t_float128);
append_composite_type_field (t, "uint128", bt->builtin_uint128);
append_composite_type_field (t, "v2_double",
init_vector_type (bt->builtin_double, 2));
append_composite_type_field (t, "v16_int8",
init_vector_type (bt->builtin_int8, 16));
- TYPE_VECTOR (t) = 1;
- TYPE_NAME (t) = "ppc_builtin_type_vec128";
+ t->set_is_vector (true);
+ t->set_name ("ppc_builtin_type_vec128");
tdep->ppc_builtin_type_vec128 = t;
}
static const char *
rs6000_register_name (struct gdbarch *gdbarch, int regno)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_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
&& regno < tdep->ppc_vsr0_upper_regnum + ppc_num_gprs)
return "";
+ /* Hide the upper halves of the cvs0~cvs31 registers. */
+ if (PPC_CVSR0_UPPER_REGNUM <= regno
+ && regno < PPC_CVSR0_UPPER_REGNUM + ppc_num_gprs)
+ return "";
+
/* Check if the SPE pseudo registers are available. */
if (IS_SPE_PSEUDOREG (tdep, regno))
{
return dfp128_regnames[regno - tdep->ppc_dl0_regnum];
}
+ /* Check if this is a vX alias for a raw vrX vector register. */
+ if (IS_V_ALIAS_PSEUDOREG (tdep, regno))
+ {
+ static const char *const vector_alias_regnames[] = {
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
+ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
+ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
+ };
+ return vector_alias_regnames[regno - tdep->ppc_v0_alias_regnum];
+ }
+
/* Check if this is a VSX pseudo-register. */
if (IS_VSX_PSEUDOREG (tdep, regno))
{
return efpr_regnames[regno - tdep->ppc_efpr0_regnum];
}
+ /* Check if this is a Checkpointed DFP pseudo-register. */
+ if (IS_CDFP_PSEUDOREG (tdep, regno))
+ {
+ static const char *const cdfp128_regnames[] = {
+ "cdl0", "cdl1", "cdl2", "cdl3",
+ "cdl4", "cdl5", "cdl6", "cdl7",
+ "cdl8", "cdl9", "cdl10", "cdl11",
+ "cdl12", "cdl13", "cdl14", "cdl15"
+ };
+ return cdfp128_regnames[regno - tdep->ppc_cdl0_regnum];
+ }
+
+ /* Check if this is a Checkpointed VSX pseudo-register. */
+ if (IS_CVSX_PSEUDOREG (tdep, regno))
+ {
+ static const char *const cvsx_regnames[] = {
+ "cvs0", "cvs1", "cvs2", "cvs3", "cvs4", "cvs5", "cvs6", "cvs7",
+ "cvs8", "cvs9", "cvs10", "cvs11", "cvs12", "cvs13", "cvs14",
+ "cvs15", "cvs16", "cvs17", "cvs18", "cvs19", "cvs20", "cvs21",
+ "cvs22", "cvs23", "cvs24", "cvs25", "cvs26", "cvs27", "cvs28",
+ "cvs29", "cvs30", "cvs31", "cvs32", "cvs33", "cvs34", "cvs35",
+ "cvs36", "cvs37", "cvs38", "cvs39", "cvs40", "cvs41", "cvs42",
+ "cvs43", "cvs44", "cvs45", "cvs46", "cvs47", "cvs48", "cvs49",
+ "cvs50", "cvs51", "cvs52", "cvs53", "cvs54", "cvs55", "cvs56",
+ "cvs57", "cvs58", "cvs59", "cvs60", "cvs61", "cvs62", "cvs63"
+ };
+ return cvsx_regnames[regno - tdep->ppc_cvsr0_regnum];
+ }
+
+ /* Check if the this is a Checkpointed Extended FP pseudo-register. */
+ if (IS_CEFP_PSEUDOREG (tdep, regno))
+ {
+ static const char *const cefpr_regnames[] = {
+ "cf32", "cf33", "cf34", "cf35", "cf36", "cf37", "cf38",
+ "cf39", "cf40", "cf41", "cf42", "cf43", "cf44", "cf45",
+ "cf46", "cf47", "cf48", "cf49", "cf50", "cf51",
+ "cf52", "cf53", "cf54", "cf55", "cf56", "cf57",
+ "cf58", "cf59", "cf60", "cf61", "cf62", "cf63"
+ };
+ return cefpr_regnames[regno - tdep->ppc_cefpr0_regnum];
+ }
+
return tdesc_register_name (gdbarch, regno);
}
static struct type *
rs6000_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
- /* These are the only pseudo-registers we support. */
- gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
- || IS_DFP_PSEUDOREG (tdep, regnum)
- || IS_VSX_PSEUDOREG (tdep, regnum)
- || IS_EFP_PSEUDOREG (tdep, regnum));
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
/* These are the e500 pseudo-registers. */
if (IS_SPE_PSEUDOREG (tdep, regnum))
return rs6000_builtin_type_vec64 (gdbarch);
- else if (IS_DFP_PSEUDOREG (tdep, regnum))
+ else if (IS_DFP_PSEUDOREG (tdep, regnum)
+ || IS_CDFP_PSEUDOREG (tdep, regnum))
/* PPC decimal128 pseudo-registers. */
return builtin_type (gdbarch)->builtin_declong;
- else if (IS_VSX_PSEUDOREG (tdep, regnum))
+ else if (IS_V_ALIAS_PSEUDOREG (tdep, regnum))
+ return gdbarch_register_type (gdbarch,
+ tdep->ppc_vr0_regnum
+ + (regnum
+ - tdep->ppc_v0_alias_regnum));
+ else if (IS_VSX_PSEUDOREG (tdep, regnum)
+ || IS_CVSX_PSEUDOREG (tdep, regnum))
/* POWER7 VSX pseudo-registers. */
return rs6000_builtin_type_vec128 (gdbarch);
- else
+ else if (IS_EFP_PSEUDOREG (tdep, regnum)
+ || IS_CEFP_PSEUDOREG (tdep, regnum))
/* POWER7 Extended FP pseudo-registers. */
return builtin_type (gdbarch)->builtin_double;
+ else
+ internal_error (_("rs6000_pseudo_register_type: "
+ "called on unexpected register '%s' (%d)"),
+ gdbarch_register_name (gdbarch, regnum), regnum);
}
-/* Is REGNUM a member of REGGROUP? */
+/* Check if REGNUM is a member of REGGROUP. We only need to handle
+ the vX aliases for the vector registers by always returning false
+ to avoid duplicated information in "info register vector/all",
+ since the raw vrX registers will already show in these cases. For
+ other pseudo-registers we use the default membership function. */
+
static int
rs6000_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
- struct reggroup *group)
+ const struct reggroup *group)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
- /* These are the only pseudo-registers we support. */
- gdb_assert (IS_SPE_PSEUDOREG (tdep, regnum)
- || IS_DFP_PSEUDOREG (tdep, regnum)
- || IS_VSX_PSEUDOREG (tdep, regnum)
- || IS_EFP_PSEUDOREG (tdep, regnum));
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
- /* These are the e500 pseudo-registers or the POWER7 VSX registers. */
- if (IS_SPE_PSEUDOREG (tdep, regnum) || IS_VSX_PSEUDOREG (tdep, regnum))
- return group == all_reggroup || group == vector_reggroup;
+ if (IS_V_ALIAS_PSEUDOREG (tdep, regnum))
+ return 0;
else
- /* PPC decimal128 or Extended FP pseudo-registers. */
- return group == all_reggroup || group == float_reggroup;
+ return default_register_reggroup_p (gdbarch, regnum, group);
}
/* The register format for RS/6000 floating point registers is always
rs6000_convert_register_p (struct gdbarch *gdbarch, int regnum,
struct type *type)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
return (tdep->ppc_fp0_regnum >= 0
&& regnum >= tdep->ppc_fp0_regnum
&& regnum < tdep->ppc_fp0_regnum + ppc_num_fprs
- && TYPE_CODE (type) == TYPE_CODE_FLT
- && TYPE_LENGTH (type)
- != TYPE_LENGTH (builtin_type (gdbarch)->builtin_double));
+ && type->code () == TYPE_CODE_FLT
+ && (type->length ()
+ != builtin_type (gdbarch)->builtin_double->length ()));
}
static int
-rs6000_register_to_value (struct frame_info *frame,
- int regnum,
- struct type *type,
- gdb_byte *to,
+rs6000_register_to_value (frame_info_ptr frame,
+ int regnum,
+ struct type *type,
+ gdb_byte *to,
int *optimizedp, int *unavailablep)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
gdb_byte from[PPC_MAX_REGISTER_SIZE];
- gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
+ gdb_assert (type->code () == TYPE_CODE_FLT);
if (!get_frame_register_bytes (frame, regnum, 0,
- register_size (gdbarch, regnum),
- from, optimizedp, unavailablep))
+ gdb::make_array_view (from,
+ register_size (gdbarch,
+ regnum)),
+ optimizedp, unavailablep))
return 0;
target_float_convert (from, builtin_type (gdbarch)->builtin_double,
}
static void
-rs6000_value_to_register (struct frame_info *frame,
- int regnum,
- struct type *type,
- const gdb_byte *from)
+rs6000_value_to_register (frame_info_ptr frame,
+ int regnum,
+ struct type *type,
+ const gdb_byte *from)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
gdb_byte to[PPC_MAX_REGISTER_SIZE];
- gdb_assert (TYPE_CODE (type) == TYPE_CODE_FLT);
+ gdb_assert (type->code () == TYPE_CODE_FLT);
target_float_convert (from, type,
to, builtin_type (gdbarch)->builtin_double);
struct regcache *regcache, int ev_reg, void *buffer)
{
struct gdbarch *arch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (arch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_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 = gdbarch_tdep<ppc_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);
- int reg_index = reg_nr - tdep->ppc_dl0_regnum;
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ int reg_index, fp0;
enum register_status status;
+ if (IS_DFP_PSEUDOREG (tdep, reg_nr))
+ {
+ reg_index = reg_nr - tdep->ppc_dl0_regnum;
+ fp0 = PPC_F0_REGNUM;
+ }
+ else
+ {
+ gdb_assert (IS_CDFP_PSEUDOREG (tdep, reg_nr));
+
+ reg_index = reg_nr - tdep->ppc_cdl0_regnum;
+ fp0 = PPC_CF0_REGNUM;
+ }
+
if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
{
/* Read two FP registers to form a whole dl register. */
- status = regcache->raw_read (tdep->ppc_fp0_regnum +
- 2 * reg_index, buffer);
+ status = regcache->raw_read (fp0 + 2 * reg_index, buffer);
if (status == REG_VALID)
- status = regcache->raw_read (tdep->ppc_fp0_regnum +
- 2 * reg_index + 1, buffer + 8);
+ status = regcache->raw_read (fp0 + 2 * reg_index + 1,
+ buffer + 8);
}
else
{
- status = regcache->raw_read (tdep->ppc_fp0_regnum +
- 2 * reg_index + 1, buffer);
+ status = regcache->raw_read (fp0 + 2 * reg_index + 1, buffer);
if (status == REG_VALID)
- status = regcache->raw_read (tdep->ppc_fp0_regnum +
- 2 * reg_index, buffer + 8);
+ status = regcache->raw_read (fp0 + 2 * reg_index, buffer + 8);
}
return 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);
- int reg_index = reg_nr - tdep->ppc_dl0_regnum;
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ int reg_index, fp0;
+
+ if (IS_DFP_PSEUDOREG (tdep, reg_nr))
+ {
+ reg_index = reg_nr - tdep->ppc_dl0_regnum;
+ fp0 = PPC_F0_REGNUM;
+ }
+ else
+ {
+ gdb_assert (IS_CDFP_PSEUDOREG (tdep, reg_nr));
+
+ reg_index = reg_nr - tdep->ppc_cdl0_regnum;
+ fp0 = PPC_CF0_REGNUM;
+ }
if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
{
/* Write each half of the dl register into a separate
- FP register. */
- regcache->raw_write (tdep->ppc_fp0_regnum +
- 2 * reg_index, buffer);
- regcache->raw_write (tdep->ppc_fp0_regnum +
- 2 * reg_index + 1, buffer + 8);
+ FP register. */
+ regcache->raw_write (fp0 + 2 * reg_index, buffer);
+ regcache->raw_write (fp0 + 2 * reg_index + 1, buffer + 8);
}
else
{
- regcache->raw_write (tdep->ppc_fp0_regnum +
- 2 * reg_index + 1, buffer);
- regcache->raw_write (tdep->ppc_fp0_regnum +
- 2 * reg_index, buffer + 8);
+ regcache->raw_write (fp0 + 2 * reg_index + 1, buffer);
+ regcache->raw_write (fp0 + 2 * reg_index, buffer + 8);
}
}
+/* Read method for the vX aliases for the raw vrX registers. */
+
+static enum register_status
+v_alias_pseudo_register_read (struct gdbarch *gdbarch,
+ readable_regcache *regcache, int reg_nr,
+ gdb_byte *buffer)
+{
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
+
+ return regcache->raw_read (tdep->ppc_vr0_regnum
+ + (reg_nr - tdep->ppc_v0_alias_regnum),
+ buffer);
+}
+
+/* Write method for the vX aliases for the raw vrX registers. */
+
+static void
+v_alias_pseudo_register_write (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ int reg_nr, const gdb_byte *buffer)
+{
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
+
+ regcache->raw_write (tdep->ppc_vr0_regnum
+ + (reg_nr - tdep->ppc_v0_alias_regnum), buffer);
+}
+
/* Read method for POWER7 VSX pseudo-registers. */
static enum register_status
vsx_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
int reg_nr, gdb_byte *buffer)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ int reg_index, vr0, fp0, vsr0_upper;
enum register_status status;
+ if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+ {
+ reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+ vr0 = PPC_VR0_REGNUM;
+ fp0 = PPC_F0_REGNUM;
+ vsr0_upper = PPC_VSR0_UPPER_REGNUM;
+ }
+ else
+ {
+ gdb_assert (IS_CVSX_PSEUDOREG (tdep, reg_nr));
+
+ reg_index = reg_nr - tdep->ppc_cvsr0_regnum;
+ vr0 = PPC_CVR0_REGNUM;
+ fp0 = PPC_CF0_REGNUM;
+ vsr0_upper = PPC_CVSR0_UPPER_REGNUM;
+ }
+
/* Read the portion that overlaps the VMX registers. */
if (reg_index > 31)
- status = regcache->raw_read (tdep->ppc_vr0_regnum +
- reg_index - 32, buffer);
+ status = regcache->raw_read (vr0 + reg_index - 32, buffer);
else
/* Read the portion that overlaps the FPR registers. */
if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
{
- status = regcache->raw_read (tdep->ppc_fp0_regnum +
- reg_index, buffer);
+ status = regcache->raw_read (fp0 + reg_index, buffer);
if (status == REG_VALID)
- status = regcache->raw_read (tdep->ppc_vsr0_upper_regnum +
- reg_index, buffer + 8);
+ status = regcache->raw_read (vsr0_upper + reg_index,
+ buffer + 8);
}
else
{
- status = regcache->raw_read (tdep->ppc_fp0_regnum +
- reg_index, buffer + 8);
+ status = regcache->raw_read (fp0 + reg_index, buffer + 8);
if (status == REG_VALID)
- status = regcache->raw_read (tdep->ppc_vsr0_upper_regnum +
- reg_index, buffer);
+ status = regcache->raw_read (vsr0_upper + reg_index, buffer);
}
return 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);
- int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ int reg_index, vr0, fp0, vsr0_upper;
+
+ if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+ {
+ reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+ vr0 = PPC_VR0_REGNUM;
+ fp0 = PPC_F0_REGNUM;
+ vsr0_upper = PPC_VSR0_UPPER_REGNUM;
+ }
+ else
+ {
+ gdb_assert (IS_CVSX_PSEUDOREG (tdep, reg_nr));
+
+ reg_index = reg_nr - tdep->ppc_cvsr0_regnum;
+ vr0 = PPC_CVR0_REGNUM;
+ fp0 = PPC_CF0_REGNUM;
+ vsr0_upper = PPC_CVSR0_UPPER_REGNUM;
+ }
/* Write the portion that overlaps the VMX registers. */
if (reg_index > 31)
- regcache->raw_write (tdep->ppc_vr0_regnum +
- reg_index - 32, buffer);
+ regcache->raw_write (vr0 + reg_index - 32, buffer);
else
/* Write the portion that overlaps the FPR registers. */
if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
{
- regcache->raw_write (tdep->ppc_fp0_regnum +
- reg_index, buffer);
- regcache->raw_write (tdep->ppc_vsr0_upper_regnum +
- reg_index, buffer + 8);
+ regcache->raw_write (fp0 + reg_index, buffer);
+ regcache->raw_write (vsr0_upper + reg_index, buffer + 8);
}
else
{
- regcache->raw_write (tdep->ppc_fp0_regnum +
- reg_index, buffer + 8);
- regcache->raw_write (tdep->ppc_vsr0_upper_regnum +
- reg_index, buffer);
+ regcache->raw_write (fp0 + reg_index, buffer + 8);
+ regcache->raw_write (vsr0_upper + reg_index, buffer);
}
}
/* Read method for POWER7 Extended FP pseudo-registers. */
static enum register_status
-efpr_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
+efp_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
int reg_nr, gdb_byte *buffer)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ int reg_index, vr0;
+
+ if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+ {
+ reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+ vr0 = PPC_VR0_REGNUM;
+ }
+ else
+ {
+ gdb_assert (IS_CEFP_PSEUDOREG (tdep, reg_nr));
+
+ reg_index = reg_nr - tdep->ppc_cefpr0_regnum;
+ vr0 = PPC_CVR0_REGNUM;
+ }
+
int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
/* Read the portion that overlaps the VMX register. */
- return regcache->raw_read_part (tdep->ppc_vr0_regnum + reg_index,
- offset, register_size (gdbarch, reg_nr),
+ return regcache->raw_read_part (vr0 + reg_index, offset,
+ register_size (gdbarch, reg_nr),
buffer);
}
/* Write method for POWER7 Extended FP pseudo-registers. */
static void
-efpr_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
+efp_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
int reg_nr, const gdb_byte *buffer)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ int reg_index, vr0;
int offset = gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG ? 0 : 8;
+ if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+ {
+ reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+ vr0 = PPC_VR0_REGNUM;
+ }
+ else
+ {
+ gdb_assert (IS_CEFP_PSEUDOREG (tdep, reg_nr));
+
+ reg_index = reg_nr - tdep->ppc_cefpr0_regnum;
+ vr0 = PPC_CVR0_REGNUM;
+
+ /* The call to raw_write_part fails silently if the initial read
+ of the read-update-write sequence returns an invalid status,
+ so we check this manually and throw an error if needed. */
+ regcache->raw_update (vr0 + reg_index);
+ if (regcache->get_register_status (vr0 + reg_index) != REG_VALID)
+ error (_("Cannot write to the checkpointed EFP register, "
+ "the corresponding vector register is unavailable."));
+ }
+
/* Write the portion that overlaps the VMX register. */
- regcache->raw_write_part (tdep->ppc_vr0_regnum + reg_index, offset,
+ regcache->raw_write_part (vr0 + reg_index, offset,
register_size (gdbarch, reg_nr), buffer);
}
int reg_nr, gdb_byte *buffer)
{
struct gdbarch *regcache_arch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
gdb_assert (regcache_arch == gdbarch);
if (IS_SPE_PSEUDOREG (tdep, reg_nr))
return e500_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
- else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
+ else if (IS_DFP_PSEUDOREG (tdep, reg_nr)
+ || IS_CDFP_PSEUDOREG (tdep, reg_nr))
return dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
- else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+ else if (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr))
+ return v_alias_pseudo_register_read (gdbarch, regcache, reg_nr,
+ buffer);
+ else if (IS_VSX_PSEUDOREG (tdep, reg_nr)
+ || IS_CVSX_PSEUDOREG (tdep, reg_nr))
return vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
- else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
- return efpr_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+ else if (IS_EFP_PSEUDOREG (tdep, reg_nr)
+ || IS_CEFP_PSEUDOREG (tdep, reg_nr))
+ return efp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
else
- internal_error (__FILE__, __LINE__,
- _("rs6000_pseudo_register_read: "
+ internal_error (_("rs6000_pseudo_register_read: "
"called on unexpected register '%s' (%d)"),
gdbarch_register_name (gdbarch, reg_nr), reg_nr);
}
int reg_nr, const gdb_byte *buffer)
{
struct gdbarch *regcache_arch = regcache->arch ();
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
gdb_assert (regcache_arch == gdbarch);
if (IS_SPE_PSEUDOREG (tdep, reg_nr))
e500_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
- else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
+ else if (IS_DFP_PSEUDOREG (tdep, reg_nr)
+ || IS_CDFP_PSEUDOREG (tdep, reg_nr))
dfp_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
- else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+ else if (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr))
+ v_alias_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+ else if (IS_VSX_PSEUDOREG (tdep, reg_nr)
+ || IS_CVSX_PSEUDOREG (tdep, reg_nr))
vsx_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
- else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
- efpr_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+ else if (IS_EFP_PSEUDOREG (tdep, reg_nr)
+ || IS_CEFP_PSEUDOREG (tdep, reg_nr))
+ efp_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
else
- internal_error (__FILE__, __LINE__,
- _("rs6000_pseudo_register_write: "
+ internal_error (_("rs6000_pseudo_register_write: "
"called on unexpected register '%s' (%d)"),
gdbarch_register_name (gdbarch, reg_nr), reg_nr);
}
-static int
-rs6000_ax_pseudo_register_collect (struct gdbarch *gdbarch,
- struct agent_expr *ax, int reg_nr)
+/* Set the register mask in AX with the registers that form the DFP or
+ checkpointed DFP pseudo-register REG_NR. */
+
+static void
+dfp_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+ struct agent_expr *ax, int reg_nr)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- if (IS_SPE_PSEUDOREG (tdep, reg_nr))
- {
- int reg_index = reg_nr - tdep->ppc_ev0_regnum;
- ax_reg_mask (ax, tdep->ppc_gp0_regnum + reg_index);
- ax_reg_mask (ax, tdep->ppc_ev0_upper_regnum + reg_index);
- }
- else if (IS_DFP_PSEUDOREG (tdep, reg_nr))
- {
- int reg_index = reg_nr - tdep->ppc_dl0_regnum;
- ax_reg_mask (ax, tdep->ppc_fp0_regnum + 2 * reg_index);
- ax_reg_mask (ax, tdep->ppc_fp0_regnum + 2 * reg_index + 1);
- }
- else if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ int reg_index, fp0;
+
+ if (IS_DFP_PSEUDOREG (tdep, reg_nr))
{
- int reg_index = reg_nr - tdep->ppc_vsr0_regnum;
- if (reg_index > 31)
- {
- ax_reg_mask (ax, tdep->ppc_vr0_regnum + reg_index - 32);
- }
- else
- {
- ax_reg_mask (ax, tdep->ppc_fp0_regnum + reg_index);
- ax_reg_mask (ax, tdep->ppc_vsr0_upper_regnum + reg_index);
- }
+ reg_index = reg_nr - tdep->ppc_dl0_regnum;
+ fp0 = PPC_F0_REGNUM;
}
- else if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+ else
{
- int reg_index = reg_nr - tdep->ppc_efpr0_regnum;
- ax_reg_mask (ax, tdep->ppc_vr0_regnum + reg_index);
+ gdb_assert (IS_CDFP_PSEUDOREG (tdep, reg_nr));
+
+ reg_index = reg_nr - tdep->ppc_cdl0_regnum;
+ fp0 = PPC_CF0_REGNUM;
}
- else
- internal_error (__FILE__, __LINE__,
- _("rs6000_pseudo_register_collect: "
- "called on unexpected register '%s' (%d)"),
- gdbarch_register_name (gdbarch, reg_nr), reg_nr);
- return 0;
+
+ ax_reg_mask (ax, fp0 + 2 * reg_index);
+ ax_reg_mask (ax, fp0 + 2 * reg_index + 1);
}
+/* Set the register mask in AX with the raw vector register that
+ corresponds to its REG_NR alias. */
static void
-rs6000_gen_return_address (struct gdbarch *gdbarch,
- struct agent_expr *ax, struct axs_value *value,
- CORE_ADDR scope)
+v_alias_pseudo_register_collect (struct gdbarch *gdbarch,
+ struct agent_expr *ax, int reg_nr)
{
- struct gdbarch_tdep *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;
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
+
+ ax_reg_mask (ax, tdep->ppc_vr0_regnum
+ + (reg_nr - tdep->ppc_v0_alias_regnum));
}
+/* Set the register mask in AX with the registers that form the VSX or
+ checkpointed VSX pseudo-register REG_NR. */
-/* Convert a DBX STABS register number to a GDB register number. */
-static int
-rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
+static void
+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 = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ int reg_index, vr0, fp0, vsr0_upper;
- if (0 <= num && num <= 31)
- return tdep->ppc_gp0_regnum + num;
- else if (32 <= num && num <= 63)
- /* FIXME: jimb/2004-05-05: What should we do when the debug info
- specifies registers the architecture doesn't have? Our
- callers don't check the value we return. */
- return tdep->ppc_fp0_regnum + (num - 32);
+ if (IS_VSX_PSEUDOREG (tdep, reg_nr))
+ {
+ reg_index = reg_nr - tdep->ppc_vsr0_regnum;
+ vr0 = PPC_VR0_REGNUM;
+ fp0 = PPC_F0_REGNUM;
+ vsr0_upper = PPC_VSR0_UPPER_REGNUM;
+ }
+ else
+ {
+ gdb_assert (IS_CVSX_PSEUDOREG (tdep, reg_nr));
+
+ reg_index = reg_nr - tdep->ppc_cvsr0_regnum;
+ vr0 = PPC_CVR0_REGNUM;
+ fp0 = PPC_CF0_REGNUM;
+ vsr0_upper = PPC_CVSR0_UPPER_REGNUM;
+ }
+
+ if (reg_index > 31)
+ {
+ ax_reg_mask (ax, vr0 + reg_index - 32);
+ }
+ else
+ {
+ ax_reg_mask (ax, fp0 + reg_index);
+ ax_reg_mask (ax, vsr0_upper + reg_index);
+ }
+}
+
+/* Set the register mask in AX with the register that corresponds to
+ the EFP or checkpointed EFP pseudo-register REG_NR. */
+
+static void
+efp_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+ struct agent_expr *ax, int reg_nr)
+{
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ int reg_index, vr0;
+
+ if (IS_EFP_PSEUDOREG (tdep, reg_nr))
+ {
+ reg_index = reg_nr - tdep->ppc_efpr0_regnum;
+ vr0 = PPC_VR0_REGNUM;
+ }
+ else
+ {
+ gdb_assert (IS_CEFP_PSEUDOREG (tdep, reg_nr));
+
+ reg_index = reg_nr - tdep->ppc_cefpr0_regnum;
+ vr0 = PPC_CVR0_REGNUM;
+ }
+
+ ax_reg_mask (ax, vr0 + reg_index);
+}
+
+static int
+rs6000_ax_pseudo_register_collect (struct gdbarch *gdbarch,
+ struct agent_expr *ax, int reg_nr)
+{
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ if (IS_SPE_PSEUDOREG (tdep, reg_nr))
+ {
+ int reg_index = reg_nr - tdep->ppc_ev0_regnum;
+ ax_reg_mask (ax, tdep->ppc_gp0_regnum + reg_index);
+ ax_reg_mask (ax, tdep->ppc_ev0_upper_regnum + reg_index);
+ }
+ else if (IS_DFP_PSEUDOREG (tdep, reg_nr)
+ || IS_CDFP_PSEUDOREG (tdep, reg_nr))
+ {
+ dfp_ax_pseudo_register_collect (gdbarch, ax, reg_nr);
+ }
+ else if (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr))
+ {
+ v_alias_pseudo_register_collect (gdbarch, ax, reg_nr);
+ }
+ else if (IS_VSX_PSEUDOREG (tdep, reg_nr)
+ || IS_CVSX_PSEUDOREG (tdep, reg_nr))
+ {
+ vsx_ax_pseudo_register_collect (gdbarch, ax, reg_nr);
+ }
+ else if (IS_EFP_PSEUDOREG (tdep, reg_nr)
+ || IS_CEFP_PSEUDOREG (tdep, reg_nr))
+ {
+ efp_ax_pseudo_register_collect (gdbarch, ax, reg_nr);
+ }
+ else
+ internal_error (_("rs6000_pseudo_register_collect: "
+ "called on unexpected register '%s' (%d)"),
+ gdbarch_register_name (gdbarch, reg_nr), reg_nr);
+ return 0;
+}
+
+
+static void
+rs6000_gen_return_address (struct gdbarch *gdbarch,
+ struct agent_expr *ax, struct axs_value *value,
+ CORE_ADDR scope)
+{
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ value->type = register_type (gdbarch, tdep->ppc_lr_regnum);
+ value->kind = axs_lvalue_register;
+ value->u.reg = tdep->ppc_lr_regnum;
+}
+
+
+/* Convert a DBX STABS register number to a GDB register number. */
+static int
+rs6000_stab_reg_to_regnum (struct gdbarch *gdbarch, int num)
+{
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+
+ if (0 <= num && num <= 31)
+ return tdep->ppc_gp0_regnum + num;
+ else if (32 <= num && num <= 63)
+ /* FIXME: jimb/2004-05-05: What should we do when the debug info
+ specifies registers the architecture doesn't have? Our
+ callers don't check the value we return. */
+ return tdep->ppc_fp0_regnum + (num - 32);
else if (77 <= num && num <= 108)
return tdep->ppc_vr0_regnum + (num - 77);
else if (1200 <= num && num < 1200 + 32)
switch (num)
{
case 64:
- return tdep->ppc_mq_regnum;
+ return tdep->ppc_mq_regnum;
case 65:
- return tdep->ppc_lr_regnum;
+ return tdep->ppc_lr_regnum;
case 66:
- return tdep->ppc_ctr_regnum;
+ return tdep->ppc_ctr_regnum;
case 76:
- return tdep->ppc_xer_regnum;
+ return tdep->ppc_xer_regnum;
case 109:
- return tdep->ppc_vrsave_regnum;
+ return tdep->ppc_vrsave_regnum;
case 110:
- return tdep->ppc_vrsave_regnum - 1; /* vscr */
+ return tdep->ppc_vrsave_regnum - 1; /* vscr */
case 111:
- return tdep->ppc_acc_regnum;
+ return tdep->ppc_acc_regnum;
case 112:
- return tdep->ppc_spefscr_regnum;
+ return tdep->ppc_spefscr_regnum;
default:
- return num;
+ return num;
}
}
static int
rs6000_dwarf2_reg_to_regnum (struct gdbarch *gdbarch, int num)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
if (0 <= num && num <= 31)
return tdep->ppc_gp0_regnum + num;
case 64:
return tdep->ppc_cr_regnum;
case 67:
- return tdep->ppc_vrsave_regnum - 1; /* vscr */
+ return tdep->ppc_vrsave_regnum - 1; /* vscr */
case 99:
- return tdep->ppc_acc_regnum;
+ return tdep->ppc_acc_regnum;
case 100:
- return tdep->ppc_mq_regnum;
+ return tdep->ppc_mq_regnum;
case 101:
- return tdep->ppc_xer_regnum;
+ return tdep->ppc_xer_regnum;
case 108:
- return tdep->ppc_lr_regnum;
+ return tdep->ppc_lr_regnum;
case 109:
- return tdep->ppc_ctr_regnum;
+ return tdep->ppc_ctr_regnum;
case 356:
- return tdep->ppc_vrsave_regnum;
+ return tdep->ppc_vrsave_regnum;
case 612:
- return tdep->ppc_spefscr_regnum;
- default:
- return num;
+ return tdep->ppc_spefscr_regnum;
}
+
+ /* Unknown DWARF register number. */
+ return -1;
}
/* Translate a .eh_frame register to DWARF register, or adjust a
/* Information about a particular processor variant. */
-struct variant
+struct ppc_variant
{
/* Name of this variant. */
const char *name;
unsigned long mach;
/* Target description for this variant. */
- struct target_desc **tdesc;
+ const struct target_desc **tdesc;
};
-static struct variant variants[] =
+static struct ppc_variant variants[] =
{
{"powerpc", "PowerPC user-level", bfd_arch_powerpc,
bfd_mach_ppc, &tdesc_powerpc_altivec32},
/* Return the variant corresponding to architecture ARCH and machine number
MACH. If no such variant exists, return null. */
-static const struct variant *
+static const struct ppc_variant *
find_variant_by_arch (enum bfd_architecture arch, unsigned long mach)
{
- const struct variant *v;
+ const struct ppc_variant *v;
for (v = variants; v->name; v++)
if (arch == v->arch && mach == v->mach)
}
\f
-static CORE_ADDR
-rs6000_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
-{
- return frame_unwind_register_unsigned (next_frame,
- gdbarch_pc_regnum (gdbarch));
-}
-
-static struct frame_id
-rs6000_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
-{
- return frame_id_build (get_frame_register_unsigned
- (this_frame, gdbarch_sp_regnum (gdbarch)),
- get_frame_pc (this_frame));
-}
struct rs6000_frame_cache
{
CORE_ADDR base;
CORE_ADDR initial_sp;
- struct trad_frame_saved_reg *saved_regs;
+ trad_frame_saved_reg *saved_regs;
/* Set BASE_P to true if this frame cache is properly initialized.
Otherwise set to false because some registers or memory cannot
};
static struct rs6000_frame_cache *
-rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
+rs6000_frame_cache (frame_info_ptr this_frame, void **this_cache)
{
struct rs6000_frame_cache *cache;
struct gdbarch *gdbarch = get_frame_arch (this_frame);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
struct rs6000_framedata fdata;
int wordsize = tdep->wordsize;
cache->pc = 0;
cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
- TRY
+ try
{
func = get_frame_func (this_frame);
cache->pc = func;
cache->base = get_frame_register_unsigned
(this_frame, gdbarch_sp_regnum (gdbarch));
}
- CATCH (ex, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &ex)
{
if (ex.error != NOT_AVAILABLE_ERROR)
- throw_exception (ex);
+ throw;
return (struct rs6000_frame_cache *) (*this_cache);
}
- END_CATCH
/* If the function appears to be frameless, check a couple of likely
indicators that we have simply failed to find the frame setup.
if (safe_read_memory_unsigned_integer (cache->base, wordsize,
byte_order, &backchain))
- cache->base = (CORE_ADDR) backchain;
+ cache->base = (CORE_ADDR) backchain;
}
- trad_frame_set_value (cache->saved_regs,
- gdbarch_sp_regnum (gdbarch), cache->base);
+ cache->saved_regs[gdbarch_sp_regnum (gdbarch)].set_value (cache->base);
/* if != -1, fdata.saved_fpr is the smallest number of saved_fpr.
All fpr's from saved_fpr to fp31 are saved. */
CORE_ADDR fpr_addr = cache->base + fdata.fpr_offset;
/* If skip_prologue says floating-point registers were saved,
- but the current architecture has no floating-point registers,
- then that's strange. But we have no indices to even record
- the addresses under, so we just ignore it. */
+ but the current architecture has no floating-point registers,
+ then that's strange. But we have no indices to even record
+ the addresses under, so we just ignore it. */
if (ppc_floating_point_unit_p (gdbarch))
- for (i = fdata.saved_fpr; i < ppc_num_fprs; i++)
- {
- cache->saved_regs[tdep->ppc_fp0_regnum + i].addr = fpr_addr;
- fpr_addr += 8;
- }
+ for (i = fdata.saved_fpr; i < ppc_num_fprs; i++)
+ {
+ cache->saved_regs[tdep->ppc_fp0_regnum + i].set_addr (fpr_addr);
+ fpr_addr += 8;
+ }
}
/* if != -1, fdata.saved_gpr is the smallest number of saved_gpr.
for (i = fdata.saved_gpr; i < ppc_num_gprs; i++)
{
if (fdata.gpr_mask & (1U << i))
- cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = gpr_addr;
+ cache->saved_regs[tdep->ppc_gp0_regnum + i].set_addr (gpr_addr);
gpr_addr += wordsize;
}
}
CORE_ADDR vr_addr = cache->base + fdata.vr_offset;
for (i = fdata.saved_vr; i < 32; i++)
{
- cache->saved_regs[tdep->ppc_vr0_regnum + i].addr = vr_addr;
+ cache->saved_regs[tdep->ppc_vr0_regnum + i].set_addr (vr_addr);
vr_addr += register_size (gdbarch, tdep->ppc_vr0_regnum);
}
}
for (i = fdata.saved_ev; i < ppc_num_gprs; i++)
{
- cache->saved_regs[tdep->ppc_ev0_regnum + i].addr = ev_addr;
- cache->saved_regs[tdep->ppc_gp0_regnum + i].addr = ev_addr + off;
+ cache->saved_regs[tdep->ppc_ev0_regnum + i].set_addr (ev_addr);
+ cache->saved_regs[tdep->ppc_gp0_regnum + i].set_addr (ev_addr
+ + off);
ev_addr += register_size (gdbarch, tdep->ppc_ev0_regnum);
}
}
/* If != 0, fdata.cr_offset is the offset from the frame that
holds the CR. */
if (fdata.cr_offset != 0)
- cache->saved_regs[tdep->ppc_cr_regnum].addr
- = cache->base + fdata.cr_offset;
+ cache->saved_regs[tdep->ppc_cr_regnum].set_addr (cache->base
+ + fdata.cr_offset);
/* If != 0, fdata.lr_offset is the offset from the frame that
holds the LR. */
if (fdata.lr_offset != 0)
- cache->saved_regs[tdep->ppc_lr_regnum].addr
- = cache->base + fdata.lr_offset;
+ cache->saved_regs[tdep->ppc_lr_regnum].set_addr (cache->base
+ + fdata.lr_offset);
else if (fdata.lr_register != -1)
- cache->saved_regs[tdep->ppc_lr_regnum].realreg = fdata.lr_register;
+ cache->saved_regs[tdep->ppc_lr_regnum].set_realreg (fdata.lr_register);
/* The PC is found in the link register. */
cache->saved_regs[gdbarch_pc_regnum (gdbarch)] =
cache->saved_regs[tdep->ppc_lr_regnum];
/* If != 0, fdata.vrsave_offset is the offset from the frame that
holds the VRSAVE. */
if (fdata.vrsave_offset != 0)
- cache->saved_regs[tdep->ppc_vrsave_regnum].addr
- = cache->base + fdata.vrsave_offset;
+ cache->saved_regs[tdep->ppc_vrsave_regnum].set_addr (cache->base
+ + fdata.vrsave_offset);
if (fdata.alloca_reg < 0)
/* If no alloca register used, then fi->frame is the value of the
}
static void
-rs6000_frame_this_id (struct frame_info *this_frame, void **this_cache,
+rs6000_frame_this_id (frame_info_ptr this_frame, void **this_cache,
struct frame_id *this_id)
{
struct rs6000_frame_cache *info = rs6000_frame_cache (this_frame,
}
static struct value *
-rs6000_frame_prev_register (struct frame_info *this_frame,
+rs6000_frame_prev_register (frame_info_ptr this_frame,
void **this_cache, int regnum)
{
struct rs6000_frame_cache *info = rs6000_frame_cache (this_frame,
static const struct frame_unwind rs6000_frame_unwind =
{
+ "rs6000 prologue",
NORMAL_FRAME,
default_frame_unwind_stop_reason,
rs6000_frame_this_id,
SP is restored and prev-PC is stored in LR. */
static struct rs6000_frame_cache *
-rs6000_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
+rs6000_epilogue_frame_cache (frame_info_ptr this_frame, void **this_cache)
{
struct rs6000_frame_cache *cache;
struct gdbarch *gdbarch = get_frame_arch (this_frame);
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
if (*this_cache)
return (struct rs6000_frame_cache *) *this_cache;
(*this_cache) = cache;
cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
- TRY
+ try
{
/* At this point the stack looks as if we just entered the
function, and the return address is stored in LR. */
cache->base = sp;
cache->initial_sp = sp;
- trad_frame_set_value (cache->saved_regs,
- gdbarch_pc_regnum (gdbarch), lr);
+ cache->saved_regs[gdbarch_pc_regnum (gdbarch)].set_value (lr);
}
- CATCH (ex, RETURN_MASK_ERROR)
+ catch (const gdb_exception_error &ex)
{
if (ex.error != NOT_AVAILABLE_ERROR)
- throw_exception (ex);
+ throw;
}
- END_CATCH
return cache;
}
Return the frame ID of an epilogue frame. */
static void
-rs6000_epilogue_frame_this_id (struct frame_info *this_frame,
+rs6000_epilogue_frame_this_id (frame_info_ptr this_frame,
void **this_cache, struct frame_id *this_id)
{
CORE_ADDR pc;
Return the register value of REGNUM in previous frame. */
static struct value *
-rs6000_epilogue_frame_prev_register (struct frame_info *this_frame,
+rs6000_epilogue_frame_prev_register (frame_info_ptr this_frame,
void **this_cache, int regnum)
{
struct rs6000_frame_cache *info =
static int
rs6000_epilogue_frame_sniffer (const struct frame_unwind *self,
- struct frame_info *this_frame,
+ frame_info_ptr this_frame,
void **this_prologue_cache)
{
if (frame_relative_level (this_frame) == 0)
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,
\f
static CORE_ADDR
-rs6000_frame_base_address (struct frame_info *this_frame, void **this_cache)
+rs6000_frame_base_address (frame_info_ptr this_frame, void **this_cache)
{
struct rs6000_frame_cache *info = rs6000_frame_cache (this_frame,
this_cache);
};
static const struct frame_base *
-rs6000_frame_base_sniffer (struct frame_info *this_frame)
+rs6000_frame_base_sniffer (frame_info_ptr this_frame)
{
return &rs6000_frame_base;
}
static void
ppc_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
struct dwarf2_frame_state_reg *reg,
- struct frame_info *this_frame)
+ frame_info_ptr this_frame)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_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. */
bfd_size_type size;
gdb_byte *ptr;
int success = 0;
- int vector_abi;
if (!abfd)
return 0;
/* Using Tag_GNU_Power_ABI_Vector here is a bit of a hack, as the user
could be using the SPE vector abi without actually using any spe
bits whatsoever. But it's close enough for now. */
- vector_abi = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_GNU,
- Tag_GNU_Power_ABI_Vector);
+ int vector_abi = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_GNU,
+ Tag_GNU_Power_ABI_Vector);
if (vector_abi == 3)
return 1;
#endif
if (!sect)
return 0;
- size = bfd_get_section_size (sect);
+ size = bfd_section_size (sect);
contents = (gdb_byte *) xmalloc (size);
if (!bfd_get_section_contents (abfd, sect, contents, 0, size))
{
#define PPC_LEV(insn) PPC_FIELD (insn, 20, 7)
#define PPC_XT(insn) ((PPC_TX (insn) << 5) | PPC_T (insn))
+#define PPC_XTp(insn) ((PPC_BIT (insn, 10) << 5) \
+ | PPC_FIELD (insn, 6, 4) << 1)
+#define PPC_XSp(insn) ((PPC_BIT (insn, 10) << 5) \
+ | PPC_FIELD (insn, 6, 4) << 1)
#define PPC_XER_NB(xer) (xer & 0x7f)
+/* The following macros are for the prefixed instructions. */
+#define P_PPC_D(insn_prefix, insn_suffix) \
+ PPC_SEXT (PPC_FIELD (insn_prefix, 14, 18) << 16 \
+ | PPC_FIELD (insn_suffix, 16, 16), 34)
+#define P_PPC_TX5(insn_sufix) PPC_BIT (insn_suffix, 5)
+#define P_PPC_TX15(insn_suffix) PPC_BIT (insn_suffix, 15)
+#define P_PPC_XT(insn_suffix) ((PPC_TX (insn_suffix) << 5) \
+ | PPC_T (insn_suffix))
+#define P_PPC_XT5(insn_suffix) ((P_PPC_TX5 (insn_suffix) << 5) \
+ | PPC_T (insn_suffix))
+#define P_PPC_XT15(insn_suffix) \
+ ((P_PPC_TX15 (insn_suffix) << 5) | PPC_T (insn_suffix))
+
/* Record Vector-Scalar Registers.
For VSR less than 32, it's represented by an FPR and an VSR-upper register.
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;
return 0;
}
+/* The ppc_record_ACC_fpscr() records the changes to the VSR registers
+ modified by a floating point instruction. The ENTRY argument selects which
+ of the eight AT entries needs to be recorded. The boolean SAVE_FPSCR
+ argument is set to TRUE to indicate the FPSCR also needs to be recorded.
+ The function returns 0 on success. */
+
+static int
+ppc_record_ACC_fpscr (struct regcache *regcache, ppc_gdbarch_tdep *tdep,
+ int entry, bool save_fpscr)
+{
+ int i;
+ if (entry < 0 || entry >= 8)
+ return -1;
+
+ /* The ACC register file consists of 8 register entries, each register
+ entry consist of four 128-bit rows.
+
+ The ACC rows map to specific VSR registers.
+ ACC[0][0] -> VSR[0]
+ ACC[0][1] -> VSR[1]
+ ACC[0][2] -> VSR[2]
+ ACC[0][3] -> VSR[3]
+ ...
+ ACC[7][0] -> VSR[28]
+ ACC[7][1] -> VSR[29]
+ ACC[7][2] -> VSR[30]
+ ACC[7][3] -> VSR[31]
+
+ NOTE:
+ In ISA 3.1 the ACC is mapped on top of VSR[0] thru VSR[31].
+
+ In the future, the ACC may be implemented as an independent register file
+ rather than mapping on top of the VSRs. This will then require the ACC to
+ be assigned its own register number and the ptrace interface to be able
+ access the ACC. Note the ptrace interface for the ACC will also need to
+ be implemented. */
+
+ /* ACC maps over the same VSR space as the fp registers. */
+ for (i = 0; i < 4; i++)
+ {
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fp0_regnum
+ + entry * 4 + i);
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_vsr0_upper_regnum
+ + entry * 4 + i);
+ }
+
+ if (save_fpscr)
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+
+ return 0;
+}
+
/* Parse and record instructions primary opcode-4 at ADDR.
Return 0 if successful. */
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 = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
int ext = PPC_FIELD (insn, 21, 11);
int vra = PPC_FIELD (insn, 11, 5);
case 41: /* Vector Multiply-Sum Signed Halfword Saturate */
record_full_arch_list_add_reg (regcache, PPC_VSCR_REGNUM);
/* FALL-THROUGH */
+ case 20: /* Move To VSR Byte Mask Immediate opcode, b2 = 0,
+ ignore bit 31 */
+ case 21: /* Move To VSR Byte Mask Immediate opcode, b2 = 1,
+ ignore bit 31 */
+ case 23: /* Vector Multiply-Sum & write Carry-out Unsigned
+ Doubleword */
+ case 24: /* Vector Extract Double Unsigned Byte to VSR
+ using GPR-specified Left-Index */
+ case 25: /* Vector Extract Double Unsigned Byte to VSR
+ using GPR-specified Right-Index */
+ case 26: /* Vector Extract Double Unsigned Halfword to VSR
+ using GPR-specified Left-Index */
+ case 27: /* Vector Extract Double Unsigned Halfword to VSR
+ using GPR-specified Right-Index */
+ case 28: /* Vector Extract Double Unsigned Word to VSR
+ using GPR-specified Left-Index */
+ case 29: /* Vector Extract Double Unsigned Word to VSR
+ using GPR-specified Right-Index */
+ case 30: /* Vector Extract Double Unsigned Doubleword to VSR
+ using GPR-specified Left-Index */
+ case 31: /* Vector Extract Double Unsigned Doubleword to VSR
+ using GPR-specified Right-Index */
case 42: /* Vector Select */
case 43: /* Vector Permute */
case 59: /* Vector Permute Right-indexed */
+ case 22: /* Vector Shift
+ Left Double by Bit Immediate if insn[21] = 0
+ Right Double by Bit Immediate if insn[21] = 1 */
case 44: /* Vector Shift Left Double by Octet Immediate */
case 45: /* Vector Permute and Exclusive-OR */
case 60: /* Vector Add Extended Unsigned Quadword Modulo */
/* Bit-21 is used for RC */
switch (ext & 0x3ff)
{
+ case 5: /* Vector Rotate Left Quadword */
+ case 69: /* Vector Rotate Left Quadword then Mask Insert */
+ case 325: /* Vector Rotate Left Quadword then AND with Mask */
case 6: /* Vector Compare Equal To Unsigned Byte */
case 70: /* Vector Compare Equal To Unsigned Halfword */
case 134: /* Vector Compare Equal To Unsigned Word */
case 838: /* Vector Compare Greater Than Signed Halfword */
case 902: /* Vector Compare Greater Than Signed Word */
case 967: /* Vector Compare Greater Than Signed Doubleword */
+ case 903: /* Vector Compare Greater Than Signed Quadword */
case 518: /* Vector Compare Greater Than Unsigned Byte */
case 646: /* Vector Compare Greater Than Unsigned Word */
case 582: /* Vector Compare Greater Than Unsigned Halfword */
case 711: /* Vector Compare Greater Than Unsigned Doubleword */
+ case 647: /* Vector Compare Greater Than Unsigned Quadword */
case 966: /* Vector Compare Bounds Single-Precision */
case 198: /* Vector Compare Equal To Single-Precision */
case 454: /* Vector Compare Greater Than or Equal To Single-Precision */
+ case 455: /* Vector Compare Equal Quadword */
case 710: /* Vector Compare Greater Than Single-Precision */
case 7: /* Vector Compare Not Equal Byte */
case 71: /* Vector Compare Not Equal Halfword */
record_full_arch_list_add_reg (regcache,
tdep->ppc_vr0_regnum + PPC_VRT (insn));
return 0;
+
+ case 13:
+ switch (vra) /* Bit-21 is used for RC */
+ {
+ case 0: /* Vector String Isolate Byte Left-justified */
+ case 1: /* Vector String Isolate Byte Right-justified */
+ case 2: /* Vector String Isolate Halfword Left-justified */
+ case 3: /* Vector String Isolate Halfword Right-justified */
+ if (PPC_Rc (insn))
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_vr0_regnum
+ + PPC_VRT (insn));
+ return 0;
+ }
}
if (ext == 1538)
case 24: /* Vector Extend Sign Byte To Doubleword */
case 25: /* Vector Extend Sign Halfword To Doubleword */
case 26: /* Vector Extend Sign Word To Doubleword */
+ case 27: /* Vector Extend Sign Doubleword To Quadword */
case 28: /* Vector Count Trailing Zeros Byte */
case 29: /* Vector Count Trailing Zeros Halfword */
case 30: /* Vector Count Trailing Zeros Word */
}
}
+ if (ext == 1602)
+ {
+ switch (vra)
+ {
+ case 0: /* Vector Expand Byte Mask */
+ case 1: /* Vector Expand Halfword Mask */
+ case 2: /* Vector Expand Word Mask */
+ case 3: /* Vector Expand Doubleword Mask */
+ case 4: /* Vector Expand Quadword Mask */
+ case 16: /* Move to VSR Byte Mask */
+ case 17: /* Move to VSR Halfword Mask */
+ case 18: /* Move to VSR Word Mask */
+ case 19: /* Move to VSR Doubleword Mask */
+ case 20: /* Move to VSR Quadword Mask */
+ ppc_record_vsr (regcache, tdep, PPC_VRT (insn) + 32);
+ return 0;
+
+ case 8: /* Vector Extract Byte Mask */
+ case 9: /* Vector Extract Halfword Mask */
+ case 10: /* Vector Extract Word Mask */
+ case 11: /* Vector Extract Doubleword Mask */
+ case 12: /* Vector Extract Quadword Mask */
+
+ /* Ignore the MP bit in the LSB position of the vra value. */
+ case 24: /* Vector Count Mask Bits Byte, MP = 0 */
+ case 25: /* Vector Count Mask Bits Byte, MP = 1 */
+ case 26: /* Vector Count Mask Bits Halfword, MP = 0 */
+ case 27: /* Vector Count Mask Bits Halfword, MP = 1 */
+ case 28: /* Vector Count Mask Bits Word, MP = 0 */
+ case 29: /* Vector Count Mask Bits Word, MP = 1 */
+ case 30: /* Vector Count Mask Bits Doubleword, MP = 0 */
+ case 31: /* Vector Count Mask Bits Doubleword, MP = 1 */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RT (insn));
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum + PPC_RT (insn));
+ return 0;
+ }
+ }
+
switch (ext)
{
+
+ case 257: /* Vector Compare Unsigned Quadword */
+ case 321: /* Vector Compare Signed Quadword */
+ /* Comparison tests that always set CR field BF */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_vr0_regnum + PPC_VRT (insn));
+ return 0;
+
case 142: /* Vector Pack Unsigned Halfword Unsigned Saturate */
case 206: /* Vector Pack Unsigned Word Unsigned Saturate */
case 270: /* Vector Pack Signed Halfword Unsigned Saturate */
case 268: /* Vector Merge Low Byte */
case 332: /* Vector Merge Low Halfword */
case 396: /* Vector Merge Low Word */
+ case 397: /* Vector Clear Leftmost Bytes */
+ case 461: /* Vector Clear Rightmost Bytes */
case 526: /* Vector Unpack High Signed Byte */
case 590: /* Vector Unpack High Signed Halfword */
case 654: /* Vector Unpack Low Signed Byte */
case 780: /* Vector Splat Immediate Signed Byte */
case 844: /* Vector Splat Immediate Signed Halfword */
case 908: /* Vector Splat Immediate Signed Word */
+ case 261: /* Vector Shift Left Quadword */
case 452: /* Vector Shift Left */
+ case 517: /* Vector Shift Right Quadword */
case 708: /* Vector Shift Right */
+ case 773: /* Vector Shift Right Algebraic Quadword */
case 1036: /* Vector Shift Left by Octet */
case 1100: /* Vector Shift Right by Octet */
case 0: /* Vector Add Unsigned Byte Modulo */
case 8: /* Vector Multiply Odd Unsigned Byte */
case 72: /* Vector Multiply Odd Unsigned Halfword */
case 136: /* Vector Multiply Odd Unsigned Word */
+ case 200: /* Vector Multiply Odd Unsigned Doubleword */
case 264: /* Vector Multiply Odd Signed Byte */
case 328: /* Vector Multiply Odd Signed Halfword */
case 392: /* Vector Multiply Odd Signed Word */
+ case 456: /* Vector Multiply Odd Signed Doubleword */
case 520: /* Vector Multiply Even Unsigned Byte */
case 584: /* Vector Multiply Even Unsigned Halfword */
case 648: /* Vector Multiply Even Unsigned Word */
+ case 712: /* Vector Multiply Even Unsigned Doubleword */
case 776: /* Vector Multiply Even Signed Byte */
case 840: /* Vector Multiply Even Signed Halfword */
case 904: /* Vector Multiply Even Signed Word */
+ case 968: /* Vector Multiply Even Signed Doubleword */
+ case 457: /* Vector Multiply Low Doubleword */
+ case 649: /* Vector Multiply High Unsigned Word */
+ case 713: /* Vector Multiply High Unsigned Doubleword */
+ case 905: /* Vector Multiply High Signed Word */
+ case 969: /* Vector Multiply High Signed Doubleword */
+ case 11: /* Vector Divide Unsigned Quadword */
+ case 203: /* Vector Divide Unsigned Doubleword */
+ case 139: /* Vector Divide Unsigned Word */
+ case 267: /* Vector Divide Signed Quadword */
+ case 459: /* Vector Divide Signed Doubleword */
+ case 395: /* Vector Divide Signed Word */
+ case 523: /* Vector Divide Extended Unsigned Quadword */
+ case 715: /* Vector Divide Extended Unsigned Doubleword */
+ case 651: /* Vector Divide Extended Unsigned Word */
+ case 779: /* Vector Divide Extended Signed Quadword */
+ case 971: /* Vector Divide Extended Signed Doubleword */
+ case 907: /* Vector Divide Extended Unsigned Word */
+ case 1547: /* Vector Modulo Unsigned Quadword */
+ case 1675: /* Vector Modulo Unsigned Word */
+ case 1739: /* Vector Modulo Unsigned Doubleword */
+ case 1803: /* Vector Modulo Signed Quadword */
+ case 1931: /* Vector Modulo Signed Word */
+ case 1995: /* Vector Modulo Signed Doubleword */
+
case 137: /* Vector Multiply Unsigned Word Modulo */
case 1024: /* Vector Subtract Unsigned Byte Modulo */
case 1088: /* Vector Subtract Unsigned Halfword Modulo */
case 1794: /* Vector Count Leading Zeros Byte */
case 1858: /* Vector Count Leading Zeros Halfword */
case 1922: /* Vector Count Leading Zeros Word */
+ case 1924: /* Vector Count Leading Zeros Doubleword under
+ bit Mask*/
case 1986: /* Vector Count Leading Zeros Doubleword */
+ case 1988: /* Vector Count Trailing Zeros Doubleword under bit
+ Mask */
case 1795: /* Vector Population Count Byte */
case 1859: /* Vector Population Count Halfword */
case 1923: /* Vector Population Count Word */
case 589: /* Vector Extract Unsigned Halfword */
case 653: /* Vector Extract Unsigned Word */
case 717: /* Vector Extract Doubleword */
+ case 15: /* Vector Insert Byte from VSR using GPR-specified
+ Left-Index */
+ case 79: /* Vector Insert Halfword from VSR using GPR-specified
+ Left-Index */
+ case 143: /* Vector Insert Word from VSR using GPR-specified
+ Left-Index */
+ case 207: /* Vector Insert Word from GPR using
+ immediate-specified index */
+ case 463: /* Vector Insert Doubleword from GPR using
+ immediate-specified index */
+ case 271: /* Vector Insert Byte from VSR using GPR-specified
+ Right-Index */
+ case 335: /* Vector Insert Halfword from VSR using GPR-specified
+ Right-Index */
+ case 399: /* Vector Insert Word from VSR using GPR-specified
+ Right-Index */
+ case 527: /* Vector Insert Byte from GPR using GPR-specified
+ Left-Index */
+ case 591: /* Vector Insert Halfword from GPR using GPR-specified
+ Left-Index */
+ case 655: /* Vector Insert Word from GPR using GPR-specified
+ Left-Index */
+ case 719: /* Vector Insert Doubleword from GPR using
+ GPR-specified Left-Index */
+ case 783: /* Vector Insert Byte from GPR using GPR-specified
+ Right-Index */
+ case 847: /* Vector Insert Halfword from GPR using GPR-specified
+ Left-Index */
+ case 911: /* Vector Insert Word from GPR using GPR-specified
+ Left-Index */
+ case 975: /* Vector Insert Doubleword from GPR using
+ GPR-specified Right-Index */
case 781: /* Vector Insert Byte */
case 845: /* Vector Insert Halfword */
case 909: /* Vector Insert Word */
case 973: /* Vector Insert Doubleword */
+ case 1357: /* Vector Centrifuge Doubleword */
+ case 1421: /* Vector Parallel Bits Extract Doubleword */
+ case 1485: /* Vector Parallel Bits Deposit Doubleword */
record_full_arch_list_add_reg (regcache,
tdep->ppc_vr0_regnum + PPC_VRT (insn));
return 0;
+ case 1228: /* Vector Gather every Nth Bit */
case 1549: /* Vector Extract Unsigned Byte Left-Indexed */
case 1613: /* Vector Extract Unsigned Halfword Left-Indexed */
case 1677: /* Vector Extract Unsigned Word Left-Indexed */
return 0;
}
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
- "at %s, 4-%d.\n", insn, paddress (gdbarch, addr), ext);
+ gdb_printf (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, 4-%d.\n", insn, paddress (gdbarch, addr), ext);
+ return -1;
+}
+
+/* Parse and record instructions of primary opcode 6 at ADDR.
+ Return 0 if successful. */
+
+static int
+ppc_process_record_op6 (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR addr, uint32_t insn)
+{
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ int subtype = PPC_FIELD (insn, 28, 4);
+ CORE_ADDR ea = 0;
+
+ switch (subtype)
+ {
+ case 0: /* Load VSX Vector Paired */
+ ppc_record_vsr (regcache, tdep, PPC_XTp (insn));
+ ppc_record_vsr (regcache, tdep, PPC_XTp (insn) + 1);
+ return 0;
+ case 1: /* Store VSX Vector Paired */
+ if (PPC_RA (insn) != 0)
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn), &ea);
+ ea += PPC_DQ (insn) << 4;
+ record_full_arch_list_add_mem (ea, 32);
+ return 0;
+ }
return -1;
}
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 = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
int ext = PPC_EXTOP (insn);
switch (ext & 0x01f)
return 0;
}
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
- "at %s, 19-%d.\n", insn, paddress (gdbarch, addr), ext);
+ gdb_printf (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, 19-%d.\n", insn, paddress (gdbarch, addr), ext);
+ return -1;
+}
+
+/* Parse and record instructions of primary opcode-31 with the extended opcode
+ 177. The argument is the word instruction (insn). Return 0 if successful.
+*/
+
+static int
+ppc_process_record_op31_177 (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ uint32_t insn)
+{
+ int RA_opcode = PPC_RA(insn);
+ int as = PPC_FIELD (insn, 6, 3);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+
+ switch (RA_opcode)
+ {
+ case 0: /* VSX Move From Accumulator, xxmfacc */
+ case 1: /* VSX Move To Accumulator, xxmtacc */
+ case 3: /* VSX Set Accumulator to Zero, xxsetaccz */
+ ppc_record_ACC_fpscr (regcache, tdep, as, false);
+ return 0;
+ }
return -1;
}
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 = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
int ext = PPC_EXTOP (insn);
- int tmp, nr, nb, i;
+ int tmp, nr, nb = 0, i;
CORE_ADDR at_dcsz, ea = 0;
ULONGEST rb, ra, xer;
int size = 0;
case 371: /* Move From Time Base [Phased-Out] */
case 309: /* Load Doubleword Monitored Indexed */
case 128: /* Set Boolean */
+ case 384: /* Set Boolean Condition */
+ case 416: /* Set Boolean Condition Reverse */
+ case 448: /* Set Negative Boolean Condition */
+ case 480: /* Set Negative Boolean Condition Reverse */
case 755: /* Deliver A Random Number */
record_full_arch_list_add_reg (regcache,
tdep->ppc_gp0_regnum + PPC_RT (insn));
/* These only write to RA. */
case 51: /* Move From VSR Doubleword */
+ case 59: /* Count Leading Zeros Doubleword under bit Mask */
case 115: /* Move From VSR Word and Zero */
case 122: /* Population count bytes */
+ case 155: /* Byte-Reverse Word */
+ case 156: /* Parallel Bits Deposit Doubleword */
+ case 187: /* Byte-Reverse Doubleword */
+ case 188: /* Parallel Bits Extract Doubleword */
+ case 219: /* Byte-Reverse Halfword */
+ case 220: /* Centrifuge Doubleword */
case 378: /* Population count words */
case 506: /* Population count doublewords */
case 154: /* Parity Word */
case 314: /* Convert Binary Coded Decimal To Declets */
case 508: /* Compare bytes */
case 307: /* Move From VSR Lower Doubleword */
+ case 571: /* Count Trailing Zeros Doubleword under bit Mask */
record_full_arch_list_add_reg (regcache,
tdep->ppc_gp0_regnum + PPC_RA (insn));
return 0;
record_full_arch_list_add_reg (regcache, tmp + 1);
return 0;
+ /* These write to destination register PPC_XT. */
case 179: /* Move To VSR Doubleword */
case 211: /* Move To VSR Word Algebraic */
case 243: /* Move To VSR Word and Zero */
case 524: /* Load VSX Scalar Single-Precision Indexed */
case 76: /* Load VSX Scalar as Integer Word Algebraic Indexed */
case 12: /* Load VSX Scalar as Integer Word and Zero Indexed */
+ case 13: /* Load VSX Vector Rightmost Byte Indexed */
+ case 45: /* Load VSX Vector Rightmost Halfword Indexed */
+ case 77: /* Load VSX Vector Rightmost Word Indexed */
+ case 109: /* Load VSX Vector Rightmost Doubleword Indexed */
case 844: /* Load VSX Vector Doubleword*2 Indexed */
case 332: /* Load VSX Vector Doubleword & Splat Indexed */
case 780: /* Load VSX Vector Word*4 Indexed */
ppc_record_vsr (regcache, tdep, PPC_XT (insn));
return 0;
+ case 333: /* Load VSX Vector Paired Indexed */
+ ppc_record_vsr (regcache, tdep, PPC_XTp (insn));
+ ppc_record_vsr (regcache, tdep, PPC_XTp (insn) + 1);
+ return 0;
+
/* These write RA. Update CR if RC is set. */
case 24: /* Shift Left Word */
case 26: /* Count Leading Zeros Word */
case 570: /* Count Trailing Zeros Doubleword */
case 890: /* Extend-Sign Word and Shift Left Immediate (445) */
case 890 | 1: /* Extend-Sign Word and Shift Left Immediate (445) */
+
+ if (ext == 444 && tdep->ppc_ppr_regnum >= 0
+ && (PPC_RS (insn) == PPC_RA (insn))
+ && (PPC_RA (insn) == PPC_RB (insn))
+ && !PPC_RC (insn))
+ {
+ /* or Rx,Rx,Rx alters PRI in PPR. */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_ppr_regnum);
+ return 0;
+ }
+
if (PPC_RC (insn))
record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
record_full_arch_list_add_reg (regcache,
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 141: /* Store VSX Vector Rightmost Byte Indexed */
+ case 173: /* Store VSX Vector Rightmost Halfword Indexed */
+ case 205: /* Store VSX Vector Rightmost Word Indexed */
+ case 237: /* Store VSX Vector Rightmost Doubleword Indexed */
+ switch(ext)
+ {
+ case 141: nb = 1;
+ break;
+ case 173: nb = 2;
+ break;
+ case 205: nb = 4;
+ break;
+ case 237: nb = 8;
+ break;
+ }
+ ra = 0;
+ if (PPC_RA (insn) != 0)
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + PPC_RA (insn), &ra);
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + PPC_RB (insn), &rb);
+ ea = ra + rb;
+ record_full_arch_list_add_mem (ea, nb);
return 0;
case 397: /* Store VSX Vector with Length */
record_full_arch_list_add_mem (ea, nb);
return 0;
+ case 461: /* Store VSX Vector Paired Indexed */
+ {
+ if (PPC_RA (insn) != 0)
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum
+ + PPC_RA (insn), &ea);
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum + PPC_RB (insn), &rb);
+ ea += rb;
+ record_full_arch_list_add_mem (ea, 32);
+ return 0;
+ }
+
case 710: /* Store Word Atomic */
case 742: /* Store Doubleword Atomic */
ra = 0;
case 1: /* XER */
record_full_arch_list_add_reg (regcache, tdep->ppc_xer_regnum);
return 0;
+ case 3: /* DSCR */
+ if (tdep->ppc_dscr_regnum >= 0)
+ record_full_arch_list_add_reg (regcache, tdep->ppc_dscr_regnum);
+ return 0;
case 8: /* LR */
record_full_arch_list_add_reg (regcache, tdep->ppc_lr_regnum);
return 0;
case 256: /* VRSAVE */
record_full_arch_list_add_reg (regcache, tdep->ppc_vrsave_regnum);
return 0;
+ case 815: /* TAR */
+ if (tdep->ppc_tar_regnum >= 0)
+ record_full_arch_list_add_reg (regcache, tdep->ppc_tar_regnum);
+ return 0;
+ case 896:
+ case 898: /* PPR */
+ if (tdep->ppc_ppr_regnum >= 0)
+ record_full_arch_list_add_reg (regcache, tdep->ppc_ppr_regnum);
+ return 0;
}
goto UNKNOWN_OP;
return 0;
case 1014: /* Data Cache Block set to Zero */
- if (target_auxv_search (current_top_target (), AT_DCACHEBSIZE, &at_dcsz) <= 0
+ if (target_auxv_search (AT_DCACHEBSIZE, &at_dcsz) <= 0
|| at_dcsz == 0)
at_dcsz = 128; /* Assume 128-byte cache line size (POWER8) */
ea = (ra + rb) & ~((ULONGEST) (at_dcsz - 1));
record_full_arch_list_add_mem (ea, at_dcsz);
return 0;
+
+ case 177:
+ if (ppc_process_record_op31_177 (gdbarch, regcache, insn) == 0)
+ return 0;
}
UNKNOWN_OP:
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
- "at %s, 31-%d.\n", insn, paddress (gdbarch, addr), ext);
+ gdb_printf (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, 31-%d.\n", insn, paddress (gdbarch, addr), ext);
return -1;
}
static int
ppc_process_record_op59 (struct gdbarch *gdbarch, struct regcache *regcache,
- CORE_ADDR addr, uint32_t insn)
+ CORE_ADDR addr, uint32_t insn)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
int ext = PPC_EXTOP (insn);
+ int at = PPC_FIELD (insn, 6, 3);
+
+ /* Note the mnemonics for the pmxvf64ger* instructions were officially
+ changed to pmdmxvf64ger*. The old mnemonics are still supported as
+ extended mnemonics. */
switch (ext & 0x1f)
{
return 0;
}
+ /* MMA instructions, keep looking. */
+ switch (ext >> 2) /* Additional opcode field is upper 8-bits of ext */
+ {
+ case 3: /* VSX Vector 8-bit Signed/Unsigned Integer GER, xvi8ger4 */
+ case 2: /* VSX Vector 8-bit Signed/Unsigned Integer GER Positive
+ multiply, Positive accumulate, xvi8ger4pp */
+
+ case 99: /* VSX Vector 8-bit Signed/Unsigned Integer GER with
+ Saturate Positive multiply, Positive accumulate,
+ xvi8ger4spp */
+
+ case 35: /* VSX Vector 4-bit Signed Integer GER, xvi4ger8 */
+ case 34: /* VSX Vector 4-bit Signed Integer GER Positive multiply,
+ Positive accumulate, xvi4ger8pp */
+
+ case 75: /* VSX Vector 16-bit Signed Integer GER, xvi16ger2 */
+ case 107: /* VSX Vector 16-bit Signed Integer GER Positive multiply,
+ Positive accumulate, xvi16ger2pp */
+
+ case 43: /* VSX Vector 16-bit Signed Integer GER with Saturation,
+ xvi16ger2s */
+ case 42: /* VSX Vector 16-bit Signed Integer GER with Saturation
+ Positive multiply, Positive accumulate, xvi16ger2spp */
+ ppc_record_ACC_fpscr (regcache, tdep, at, false);
+ return 0;
+
+ case 19: /* VSX Vector 16-bit Floating-Point GER, xvf16ger2 */
+ case 18: /* VSX Vector 16-bit Floating-Point GER Positive multiply,
+ Positive accumulate, xvf16ger2pp */
+ case 146: /* VSX Vector 16-bit Floating-Point GER Positive multiply,
+ Negative accumulate, xvf16ger2pn */
+ case 82: /* VSX Vector 16-bit Floating-Point GER Negative multiply,
+ Positive accumulate, xvf16ger2np */
+ case 210: /* VSX Vector 16-bit Floating-Point GER Negative multiply,
+ Negative accumulate, xvf16ger2nn */
+
+ case 27: /* VSX Vector 32-bit Floating-Point GER, xvf32ger */
+ case 26: /* VSX Vector 32-bit Floating-Point GER Positive multiply,
+ Positive accumulate, xvf32gerpp */
+ case 154: /* VSX Vector 32-bit Floating-Point GER Positive multiply,
+ Negative accumulate, xvf32gerpn */
+ case 90: /* VSX Vector 32-bit Floating-Point GER Negative multiply,
+ Positive accumulate, xvf32gernp */
+ case 218: /* VSX Vector 32-bit Floating-Point GER Negative multiply,
+ Negative accumulate, xvf32gernn */
+
+ case 59: /* VSX Vector 64-bit Floating-Point GER, pmdmxvf64ger
+ (pmxvf64ger) */
+ case 58: /* VSX Vector 64-bit Floating-Point GER Positive multiply,
+ Positive accumulate, xvf64gerpp */
+ case 186: /* VSX Vector 64-bit Floating-Point GER Positive multiply,
+ Negative accumulate, xvf64gerpn */
+ case 122: /* VSX Vector 64-bit Floating-Point GER Negative multiply,
+ Positive accumulate, xvf64gernp */
+ case 250: /* VSX Vector 64-bit Floating-Point GER Negative multiply,
+ Negative accumulate, pmdmxvf64gernn (pmxvf64gernn) */
+
+ case 51: /* VSX Vector bfloat16 GER, xvbf16ger2 */
+ case 50: /* VSX Vector bfloat16 GER Positive multiply,
+ Positive accumulate, xvbf16ger2pp */
+ case 178: /* VSX Vector bfloat16 GER Positive multiply,
+ Negative accumulate, xvbf16ger2pn */
+ case 114: /* VSX Vector bfloat16 GER Negative multiply,
+ Positive accumulate, xvbf16ger2np */
+ case 242: /* VSX Vector bfloat16 GER Negative multiply,
+ Negative accumulate, xvbf16ger2nn */
+ ppc_record_ACC_fpscr (regcache, tdep, at, true);
+ return 0;
+ }
+
switch (ext)
{
case 2: /* DFP Add */
return 0;
}
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
- "at %s, 59-%d.\n", insn, paddress (gdbarch, addr), ext);
+ gdb_printf (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, 59-%d.\n", insn, paddress (gdbarch, addr), ext);
+ return -1;
+}
+
+/* Parse and record an XX2-Form instruction with opcode 60 at ADDR. The
+ word instruction is an argument insn. Return 0 if successful. */
+
+static int
+ppc_process_record_op60_XX2 (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ CORE_ADDR addr, uint32_t insn)
+{
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ int RA_opcode = PPC_RA(insn);
+
+ switch (RA_opcode)
+ {
+ case 2: /* VSX Vector Test Least-Significant Bit by Byte */
+ case 25: /* VSX Vector round and Convert Single-Precision format
+ to Half-Precision format. Only changes the CR
+ field. */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_cr_regnum);
+ return 0;
+ case 17: /* VSX Vector Convert with round Single-Precision
+ to bfloat16 format */
+ case 24: /* VSX Vector Convert Half-Precision format to
+ Single-Precision format */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ /* Fall-through */
+ case 0: /* VSX Vector Extract Exponent Double-Precision */
+ case 1: /* VSX Vector Extract Significand Double-Precision */
+ case 7: /* VSX Vector Byte-Reverse Halfword */
+ case 8: /* VSX Vector Extract Exponent Single-Precision */
+ case 9: /* VSX Vector Extract Significand Single-Precision */
+ case 15: /* VSX Vector Byte-Reverse Word */
+ case 16: /* VSX Vector Convert bfloat16 to Single-Precision
+ format Non-signaling */
+ case 23: /* VSX Vector Byte-Reverse Doubleword */
+ case 31: /* VSX Vector Byte-Reverse Quadword */
+ ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+ return 0;
+ }
+
return -1;
}
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 = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
int ext = PPC_EXTOP (insn);
switch (ext >> 2)
{
case 0: /* VSX Scalar Extract Exponent Double-Precision */
case 1: /* VSX Scalar Extract Significand Double-Precision */
- record_full_arch_list_add_reg (regcache,
+ record_full_arch_list_add_reg (regcache,
tdep->ppc_gp0_regnum + PPC_RT (insn));
return 0;
case 16: /* VSX Scalar Convert Half-Precision format to
break;
case 475:
- switch (PPC_FIELD (insn, 11, 5))
- {
- case 24: /* VSX Vector Convert Half-Precision format to
- Single-Precision format */
- case 25: /* VSX Vector round and Convert Single-Precision format
- to Half-Precision format */
- record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
- /* FALL-THROUGH */
- case 0: /* VSX Vector Extract Exponent Double-Precision */
- case 1: /* VSX Vector Extract Significand Double-Precision */
- case 7: /* VSX Vector Byte-Reverse Halfword */
- case 8: /* VSX Vector Extract Exponent Single-Precision */
- case 9: /* VSX Vector Extract Significand Single-Precision */
- case 15: /* VSX Vector Byte-Reverse Word */
- case 23: /* VSX Vector Byte-Reverse Doubleword */
- case 31: /* VSX Vector Byte-Reverse Quadword */
- ppc_record_vsr (regcache, tdep, PPC_XT (insn));
- return 0;
- }
- break;
+ if (ppc_process_record_op60_XX2 (gdbarch, regcache, addr, insn) != 0)
+ return -1;
+ return 0;
}
switch (ext)
{
- case 360: /* VSX Vector Splat Immediate Byte */
- if (PPC_FIELD (insn, 11, 2) == 0)
+ case 360:
+ if (PPC_FIELD (insn, 11, 2) == 0) /* VSX Vector Splat Immediate Byte */
+ {
+ ppc_record_vsr (regcache, tdep, PPC_XT (insn));
+ return 0;
+ }
+ if (PPC_FIELD (insn, 11, 5) == 31) /* Load VSX Vector Special Value
+ Quadword */
{
ppc_record_vsr (regcache, tdep, PPC_XT (insn));
return 0;
}
break;
+ case 916: /* VSX Vector Generate PCV from Byte Mask */
+ case 917: /* VSX Vector Generate PCV from Halfword Mask */
+ case 948: /* VSX Vector Generate PCV from Word Mask */
+ case 949: /* VSX Vector Generate PCV from Doubleword Mask */
case 918: /* VSX Scalar Insert Exponent Double-Precision */
ppc_record_vsr (regcache, tdep, PPC_XT (insn));
return 0;
return 0;
}
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
- "at %s, 60-%d.\n", insn, paddress (gdbarch, addr), ext);
+ gdb_printf (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, 60-%d.\n", insn, paddress (gdbarch, addr), ext);
return -1;
}
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 = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
ULONGEST ea = 0;
int size;
return 0;
}
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
- "at %s.\n", insn, paddress (gdbarch, addr));
+ gdb_printf (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s.\n", insn, paddress (gdbarch, addr));
return -1;
}
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 = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
int ext = PPC_EXTOP (insn);
int tmp;
case 583:
switch (PPC_FIELD (insn, 11, 5))
- {
+ {
case 1: /* Move From FPSCR & Clear Enables */
case 20: /* Move From FPSCR Control & set DRN */
case 21: /* Move From FPSCR Control & set DRN Immediate */
tdep->ppc_fp0_regnum
+ PPC_FRT (insn));
return 0;
- }
+ }
break;
case 8: /* Floating Copy Sign */
Quad-Precision */
case 516: /* VSX Scalar Subtract Quad-Precision */
case 548: /* VSX Scalar Divide Quad-Precision */
+ case 994:
+ {
+ switch (PPC_FIELD (insn, 11, 5))
+ {
+ case 0: /* DFP Convert From Fixed Quadword Quad */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum
+ + PPC_FRT (insn));
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum
+ + PPC_FRT (insn) + 1);
+ return 0;
+ case 1: /* DFP Convert To Fixed Quadword Quad */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ ppc_record_vsr (regcache, tdep, PPC_VRT (insn) + 32);
+ return 0;
+ }
+ }
+
+ record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
+ /* FALL-THROUGH */
+ case 68: /* VSX Scalar Compare Equal Quad-Precision */
+ case 196: /* VSX Scalar Compare Greater Than or Equal
+ Quad-Precision */
+ case 228: /* VSX Scalar Compare Greater Than Quad-Precision */
+ case 676: /* VSX Scalar Maximum Type-C Quad-Precision */
+ case 740: /* VSX Scalar Minimum Type-C Quad-Precision */
record_full_arch_list_add_reg (regcache, tdep->ppc_fpscr_regnum);
/* FALL-THROUGH */
case 100: /* VSX Scalar Copy Sign Quad-Precision */
case 836:
switch (PPC_FIELD (insn, 11, 5))
{
+ case 0: /* VSX Scalar Convert with round to zero
+ Quad-Precision to Unsigned Quadword */
case 1: /* VSX Scalar truncate & Convert Quad-Precision format
to Unsigned Word format */
case 2: /* VSX Scalar Convert Unsigned Doubleword format to
Quad-Precision format */
+ case 3: /* VSX Scalar Convert with round
+ Unsigned Quadword to Quad-Precision */
+ case 8: /* VSX Scalar Convert with round to zero
+ Quad-Precision to Signed Quadword */
case 9: /* VSX Scalar truncate & Convert Quad-Precision format
to Signed Word format */
case 10: /* VSX Scalar Convert Signed Doubleword format to
Quad-Precision format */
+ case 11: /* VSX Scalar Convert with round
+ Signed Quadword to Quad-Precision */
case 17: /* VSX Scalar truncate & Convert Quad-Precision format
to Unsigned Doubleword format */
case 20: /* VSX Scalar round & Convert Quad-Precision format to
}
}
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
- "at %s, 63-%d.\n", insn, paddress (gdbarch, addr), ext);
+ gdb_printf (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, 63-%d.\n", insn, paddress (gdbarch, addr), ext);
return -1;
}
-/* Parse the current instruction and record the values of the registers and
- memory that will be changed in current instruction to "record_arch_list".
- Return -1 if something wrong. */
+/* Record the prefixed instructions with primary opcode 32. The arguments are
+ the first 32-bits of the instruction (insn_prefix), and the second 32-bits
+ of the instruction (insn_suffix). Return 0 on success. */
-int
-ppc_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
- CORE_ADDR addr)
+static int
+ppc_process_record_prefix_op42 (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ uint32_t insn_prefix, uint32_t insn_suffix)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- uint32_t insn;
- int op6, tmp, i;
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ int type = PPC_FIELD (insn_prefix, 6, 2);
+ int ST1 = PPC_FIELD (insn_prefix, 8, 1);
+
+ if (ST1 != 0)
+ return -1;
+
+ switch (type)
+ {
+ case 0: /* Prefixed Load VSX Scalar Doubleword, plxsd */
+ ppc_record_vsr (regcache, tdep, PPC_VRT (insn_suffix) + 32);
+ break;
+ case 2: /* Prefixed Load Halfword Algebraic, plha */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum
+ + PPC_RT (insn_suffix));
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+/* Record the prefixed XX3-Form instructions with primary opcode 59. The
+ arguments are the first 32-bits of the instruction (insn_prefix), and the
+ second 32-bits of the instruction (insn_suffix). Return 0 on success. */
+
+static int
+ppc_process_record_prefix_op59_XX3 (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ uint32_t insn_prefix, uint32_t insn_suffix)
+{
+ int opcode = PPC_FIELD (insn_suffix, 21, 8);
+ int type = PPC_FIELD (insn_prefix, 6, 2);
+ int ST4 = PPC_FIELD (insn_prefix, 8, 4);
+ int at = PPC_FIELD (insn_suffix, 6, 3);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+
+ /* Note, the mnemonics for the pmxvf16ger*, pmxvf32ger*,pmxvf64ger*,
+ pmxvi4ger8*, pmxvi8ger4* pmxvi16ger2* instructions were officially
+ changed to pmdmxbf16ger*, pmdmxvf32ger*, pmdmxvf64ger*, pmdmxvi4ger8*,
+ pmdmxvi8ger4*, pmdmxvi16ger* respectively. The old mnemonics are still
+ supported by the assembler as extended mnemonics. The disassembler
+ generates the new mnemonics. */
+ if (type == 3)
+ {
+ if (ST4 == 9)
+ switch (opcode)
+ {
+ case 35: /* Prefixed Masked VSX Vector 4-bit Signed Integer GER
+ MMIRR, pmdmxvi4ger8 (pmxvi4ger8) */
+ case 34: /* Prefixed Masked VSX Vector 4-bit Signed Integer GER
+ MMIRR, pmdmxvi4ger8pp (pmxvi4ger8pp) */
+
+ case 99: /* Prefixed Masked VSX Vector 8-bit Signed/Unsigned
+ Integer GER with Saturate Positive multiply,
+ Positive accumulate, xvi8ger4spp */
+
+ case 3: /* Prefixed Masked VSX Vector 8-bit Signed/Unsigned
+ Integer GER MMIRR, pmdmxvi8ger4 (pmxvi8ger4) */
+ case 2: /* Prefixed Masked VSX Vector 8-bit Signed/Unsigned
+ Integer GER Positive multiply, Positive accumulate
+ MMIRR, pmdmxvi8ger4pp (pmxvi8ger4pp) */
+
+ case 75: /* Prefixed Masked VSX Vector 16-bit Signed Integer
+ GER MMIRR, pmdmxvi16ger2 (pmxvi16ger2) */
+ case 107: /* Prefixed Masked VSX Vector 16-bit Signed Integer
+ GER Positive multiply, Positive accumulate,
+ pmdmxvi16ger2pp (pmxvi16ger2pp) */
+
+ case 43: /* Prefixed Masked VSX Vector 16-bit Signed Integer
+ GER with Saturation MMIRR, pmdmxvi16ger2s
+ (pmxvi16ger2s) */
+ case 42: /* Prefixed Masked VSX Vector 16-bit Signed Integer
+ GER with Saturation Positive multiply, Positive
+ accumulate MMIRR, pmdmxvi16ger2spp (pmxvi16ger2spp)
+ */
+ ppc_record_ACC_fpscr (regcache, tdep, at, false);
+ return 0;
+
+ case 19: /* Prefixed Masked VSX Vector 16-bit Floating-Point
+ GER MMIRR, pmdmxvf16ger2 (pmxvf16ger2) */
+ case 18: /* Prefixed Masked VSX Vector 16-bit Floating-Point
+ GER Positive multiply, Positive accumulate MMIRR,
+ pmdmxvf16ger2pp (pmxvf16ger2pp) */
+ case 146: /* Prefixed Masked VSX Vector 16-bit Floating-Point
+ GER Positive multiply, Negative accumulate MMIRR,
+ pmdmxvf16ger2pn (pmxvf16ger2pn) */
+ case 82: /* Prefixed Masked VSX Vector 16-bit Floating-Point
+ GER Negative multiply, Positive accumulate MMIRR,
+ pmdmxvf16ger2np (pmxvf16ger2np) */
+ case 210: /* Prefixed Masked VSX Vector 16-bit Floating-Point
+ GER Negative multiply, Negative accumulate MMIRR,
+ pmdmxvf16ger2nn (pmxvf16ger2nn) */
+
+ case 27: /* Prefixed Masked VSX Vector 32-bit Floating-Point
+ GER MMIRR, pmdmxvf32ger (pmxvf32ger) */
+ case 26: /* Prefixed Masked VSX Vector 32-bit Floating-Point
+ GER Positive multiply, Positive accumulate MMIRR,
+ pmdmxvf32gerpp (pmxvf32gerpp) */
+ case 154: /* Prefixed Masked VSX Vector 32-bit Floating-Point
+ GER Positive multiply, Negative accumulate MMIRR,
+ pmdmxvf32gerpn (pmxvf32gerpn) */
+ case 90: /* Prefixed Masked VSX Vector 32-bit Floating-Point
+ GER Negative multiply, Positive accumulate MMIRR,
+ pmdmxvf32gernp (pmxvf32gernp )*/
+ case 218: /* Prefixed Masked VSX Vector 32-bit Floating-Point
+ GER Negative multiply, Negative accumulate MMIRR,
+ pmdmxvf32gernn (pmxvf32gernn) */
+
+ case 59: /* Prefixed Masked VSX Vector 64-bit Floating-Point
+ GER MMIRR, pmdmxvf64ger (pmxvf64ger) */
+ case 58: /* Floating-Point GER Positive multiply, Positive
+ accumulate MMIRR, pmdmxvf64gerpp (pmxvf64gerpp) */
+ case 186: /* Prefixed Masked VSX Vector 64-bit Floating-Point
+ GER Positive multiply, Negative accumulate MMIRR,
+ pmdmxvf64gerpn (pmxvf64gerpn) */
+ case 122: /* Prefixed Masked VSX Vector 64-bit Floating-Point
+ GER Negative multiply, Positive accumulate MMIRR,
+ pmdmxvf64gernp (pmxvf64gernp) */
+ case 250: /* Prefixed Masked VSX Vector 64-bit Floating-Point
+ GER Negative multiply, Negative accumulate MMIRR,
+ pmdmxvf64gernn (pmxvf64gernn) */
+
+ case 51: /* Prefixed Masked VSX Vector bfloat16 GER MMIRR,
+ pmdmxvbf16ger2 (pmxvbf16ger2) */
+ case 50: /* Prefixed Masked VSX Vector bfloat16 GER Positive
+ multiply, Positive accumulate MMIRR,
+ pmdmxvbf16ger2pp (pmxvbf16ger2pp) */
+ case 178: /* Prefixed Masked VSX Vector bfloat16 GER Positive
+ multiply, Negative accumulate MMIRR,
+ pmdmxvbf16ger2pn (pmxvbf16ger2pn) */
+ case 114: /* Prefixed Masked VSX Vector bfloat16 GER Negative
+ multiply, Positive accumulate MMIRR,
+ pmdmxvbf16ger2np (pmxvbf16ger2np) */
+ case 242: /* Prefixed Masked VSX Vector bfloat16 GER Negative
+ multiply, Negative accumulate MMIRR,
+ pmdmxvbf16ger2nn (pmxvbf16ger2nn) */
+ ppc_record_ACC_fpscr (regcache, tdep, at, true);
+ return 0;
+ }
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+/* Record the prefixed store instructions. The arguments are the instruction
+ address, the first 32-bits of the instruction(insn_prefix) and the following
+ 32-bits of the instruction (insn_suffix). Return 0 on success. */
+
+static int
+ppc_process_record_prefix_store (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ CORE_ADDR addr, uint32_t insn_prefix,
+ uint32_t insn_suffix)
+{
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ ULONGEST iaddr = 0;
+ int size;
+ int R = PPC_BIT (insn_prefix, 11);
+ int op6 = PPC_OP6 (insn_suffix);
+
+ if (R == 0)
+ {
+ if (PPC_RA (insn_suffix) != 0)
+ regcache_raw_read_unsigned (regcache, tdep->ppc_gp0_regnum
+ + PPC_RA (insn_suffix), &iaddr);
+ }
+ else
+ {
+ iaddr = addr; /* PC relative */
+ }
+
+ switch (op6)
+ {
+ case 38:
+ size = 1; /* store byte, pstb */
+ break;
+ case 44:
+ size = 2; /* store halfword, psth */
+ break;
+ case 36:
+ case 52:
+ size = 4; /* store word, pstw, pstfs */
+ break;
+ case 54:
+ case 61:
+ size = 8; /* store double word, pstd, pstfd */
+ break;
+ case 60:
+ size = 16; /* store quadword, pstq */
+ break;
+ default: return -1;
+ }
+
+ iaddr += P_PPC_D (insn_prefix, insn_suffix);
+ record_full_arch_list_add_mem (iaddr, size);
+ return 0;
+}
+
+/* Record the prefixed instructions with primary op code 32. The arguments
+ are the first 32-bits of the instruction (insn_prefix) and the following
+ 32-bits of the instruction (insn_suffix). Return 0 on success. */
+
+static int
+ppc_process_record_prefix_op32 (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ uint32_t insn_prefix, uint32_t insn_suffix)
+{
+ int type = PPC_FIELD (insn_prefix, 6, 2);
+ int ST1 = PPC_FIELD (insn_prefix, 8, 1);
+ int ST4 = PPC_FIELD (insn_prefix, 8, 4);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+
+ if (type == 1)
+ {
+ if (ST4 == 0)
+ {
+ switch (PPC_FIELD (insn_suffix, 11, 3))
+ {
+ case 0: /* VSX Vector Splat Immediate Word 8RR, xxsplti32dx */
+ ppc_record_vsr (regcache, tdep, P_PPC_XT15 (insn_suffix));
+ return 0;
+ }
+
+ switch (PPC_FIELD (insn_suffix, 11, 4))
+ {
+ case 2: /* VSX Vector Splat Immediate Double-Precision
+ 8RR, xxspltidp */
+ case 3: /* VSX Vector Splat Immediate Word 8RR, xxspltiw */
+ ppc_record_vsr (regcache, tdep, P_PPC_XT15 (insn_suffix));
+ return 0;
+ default:
+ return -1;
+ }
+ }
+ else
+ return -1;
+
+ }
+ else if (type == 2)
+ {
+ if (ST1 == 0) /* Prefixed Load Word and Zero, plwz */
+ record_full_arch_list_add_reg (regcache, tdep->ppc_gp0_regnum
+ + PPC_RT (insn_suffix));
+ else
+ return -1;
+
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+/* Record the prefixed instructions with primary op code 33. The arguments
+ are the first 32-bits of the instruction(insn_prefix) and the following
+ 32-bits of the instruction (insn_suffix). Return 0 on success. */
+
+static int
+ppc_process_record_prefix_op33 (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ uint32_t insn_prefix, uint32_t insn_suffix)
+{
+ int type = PPC_FIELD (insn_prefix, 6, 2);
+ int ST4 = PPC_FIELD (insn_prefix, 8, 4);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+
+ if (type == 1)
+ {
+ if (ST4 == 0)
+ switch (PPC_FIELD (insn_suffix, 26, 2))
+ {
+ case 0: /* VSX Vector Blend Variable Byte 8RR, xxblendvb */
+ case 1: /* VSX Vector Blend Variable Halfword, xxblendvh */
+ case 2: /* VSX Vector Blend Variable Word, xxblendvw */
+ case 3: /* VSX Vector Blend Variable Doubleword, xxblendvd */
+ ppc_record_vsr (regcache, tdep, PPC_XT (insn_suffix));
+ break;
+ default:
+ return -1;
+ }
+ else
+ return -1;
+
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+/* Record the prefixed instructions with primary op code 34. The arguments
+ are the first 32-bits of the instruction(insn_prefix) and the following
+ 32-bits of the instruction (insn_suffix). Return 0 on success. */
+
+static int
+ppc_process_record_prefix_op34 (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ uint32_t insn_prefix, uint32_t insn_suffix)
+{
+ int type = PPC_FIELD (insn_prefix, 6, 2);
+ int ST1 = PPC_FIELD (insn_prefix, 8, 1);
+ int ST4 = PPC_FIELD (insn_prefix, 8, 4);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+
+ if (type == 1)
+ {
+ if (ST4 == 0)
+ switch (PPC_FIELD (insn_suffix, 26, 2))
+ {
+ case 0: /* VSX Vector Permute Extended 8RR, xxpermx */
+ case 1: /* VSX Vector Evaluate 8RR, xxeval */
+ ppc_record_vsr (regcache, tdep, P_PPC_XT (insn_suffix));
+ break;
+ default:
+ return -1;
+ }
+ else
+ return -1;
+
+ }
+ else if (type == 2)
+ {
+ if (ST1 == 0) /* Prefixed Load Word and Zero, plbz */
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum
+ + PPC_RT (insn_suffix));
+ else
+ return -1;
+
+ }
+ else
+ return -1;
+
+ return 0;
+}
+
+/* Record the prefixed VSX store, form DS, instructions. The arguments are the
+ instruction address (addr), the first 32-bits of the instruction
+ (insn_prefix) followed by the 32-bit instruction suffix (insn_suffix).
+ Return 0 on success. */
+
+static int
+ppc_process_record_prefix_store_vsx_ds_form (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ CORE_ADDR addr,
+ uint32_t insn_prefix,
+ uint32_t insn_suffix)
+{
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ ULONGEST ea = 0;
+ int size;
+ int R = PPC_BIT (insn_prefix, 11);
+ int type = PPC_FIELD (insn_prefix, 6, 2);
+ int ST1 = PPC_FIELD (insn_prefix, 8, 1);
+
+ if ((type == 0) && (ST1 == 0))
+ {
+ if (R == 0)
+ {
+ if (PPC_RA (insn_suffix) != 0)
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum
+ + PPC_RA (insn_suffix),
+ &ea);
+ }
+ else
+ {
+ ea = addr; /* PC relative */
+ }
+
+ ea += P_PPC_D (insn_prefix, insn_suffix);
+ switch (PPC_FIELD (insn_suffix, 0, 6))
+ {
+ case 46: /* Prefixed Store VSX Scalar Doubleword, pstxsd */
+ size = 8;
+ break;
+ case 47: /* Prefixed,Store VSX Scalar Single-Precision, pstxssp */
+ size = 4;
+ break;
+ default:
+ return -1;
+ }
+ record_full_arch_list_add_mem (ea, size);
+ return 0;
+ }
+ else
+ return -1;
+}
+
+/* Record the prefixed VSX, form D, instructions. The arguments are the
+ instruction address for PC-relative addresss (addr), the first 32-bits of
+ the instruction (insn_prefix) and the following 32-bits of the instruction
+ (insn_suffix). Return 0 on success. */
+
+static int
+ppc_process_record_prefix_vsx_d_form (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ CORE_ADDR addr,
+ uint32_t insn_prefix,
+ uint32_t insn_suffix)
+{
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ ULONGEST ea = 0;
+ int size;
+ int R = PPC_BIT (insn_prefix, 11);
+ int type = PPC_FIELD (insn_prefix, 6, 2);
+ int ST1 = PPC_FIELD (insn_prefix, 8, 1);
+
+ if ((type == 0) && (ST1 == 0))
+ {
+ switch (PPC_FIELD (insn_suffix, 0, 5))
+ {
+ case 25: /* Prefixed Load VSX Vector, plxv */
+ ppc_record_vsr (regcache, tdep, P_PPC_XT5 (insn_prefix));
+ return 0;
+ case 27: /* Prefixed Store VSX Vector 8LS, pstxv */
+ {
+ size = 16;
+ if (R == 0)
+ {
+ if (PPC_RA (insn_suffix) != 0)
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum
+ + PPC_RA (insn_suffix),
+ &ea);
+ }
+ else
+ {
+ ea = addr; /* PC relative */
+ }
+
+ ea += P_PPC_D (insn_prefix, insn_suffix);
+ record_full_arch_list_add_mem (ea, size);
+ return 0;
+ }
+ }
+ return -1;
+ }
+ else
+ return -1;
+}
+
+/* Parse the current instruction and record the values of the registers and
+ memory that will be changed in current instruction to "record_arch_list".
+ Return -1 if something wrong. */
+
+/* This handles the recording of the various prefix instructions. It takes
+ the instruction address, the first 32-bits of the instruction (insn_prefix)
+ and the following 32-bits of the instruction (insn_suffix). Return 0 on
+ success. */
+
+static int
+ppc_process_prefix_instruction (int insn_prefix, int insn_suffix,
+ CORE_ADDR addr, struct gdbarch *gdbarch,
+ struct regcache *regcache)
+{
+ int type = PPC_FIELD (insn_prefix, 6, 2);
+ int ST1 = PPC_FIELD (insn_prefix, 8, 1);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ int op6;
+
+ /* D-form has uses a 5-bit opcode in the instruction suffix */
+ if (ppc_process_record_prefix_vsx_d_form ( gdbarch, regcache, addr,
+ insn_prefix, insn_suffix) == 0)
+ goto SUCCESS;
+
+ op6 = PPC_OP6 (insn_suffix); /* 6-bit opcode in the instruction suffix */
+
+ switch (op6)
+ {
+ case 14: /* Prefixed Add Immediate, paddi */
+ if ((type == 2) && (ST1 == 0))
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum
+ + PPC_RT (insn_suffix));
+ else
+ goto UNKNOWN_PREFIX_OP;
+ break;
+
+ case 32:
+ if (ppc_process_record_prefix_op32 (gdbarch, regcache,
+ insn_prefix, insn_suffix) != 0)
+ goto UNKNOWN_PREFIX_OP;
+ break;
+
+ case 33:
+ if (ppc_process_record_prefix_op33 (gdbarch, regcache,
+ insn_prefix, insn_suffix) != 0)
+ goto UNKNOWN_PREFIX_OP;
+ break;
+
+ case 34: /* Prefixed Load Byte and Zero, plbz */
+ if (ppc_process_record_prefix_op34 (gdbarch, regcache,
+ insn_prefix, insn_suffix) != 0)
+ goto UNKNOWN_PREFIX_OP;
+ break;
+ case 40: /* Prefixed Load Halfword and Zero, plhz */
+ if ((type == 2) && (ST1 == 0))
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum
+ + PPC_RT (insn_suffix));
+ else
+ goto UNKNOWN_PREFIX_OP;
+ break;
+
+ break;
+
+ case 36: /* Prefixed Store Word, pstw */
+ case 38: /* Prefixed Store Byte, pstb */
+ case 44: /* Prefixed Store Halfword, psth */
+ case 52: /* Prefixed Store Floating-Point Single, pstfs */
+ case 54: /* Prefixed Store Floating-Point Double, pstfd */
+ case 60: /* Prefixed Store Quadword, pstq */
+ case 61: /* Prefixed Store Doubleword, pstd */
+ if (ppc_process_record_prefix_store (gdbarch, regcache, addr,
+ insn_prefix, insn_suffix) != 0)
+ goto UNKNOWN_PREFIX_OP;
+ break;
+
+ case 42:
+ if (ppc_process_record_prefix_op42 (gdbarch, regcache,
+ insn_prefix, insn_suffix) != 0)
+ goto UNKNOWN_PREFIX_OP;
+ break;
+
+ case 43: /* Prefixed Load VSX Scalar Single-Precision, plxssp */
+ if ((type == 0) && (ST1 == 0))
+ ppc_record_vsr (regcache, tdep, PPC_VRT (insn_suffix) + 32);
+ else
+ goto UNKNOWN_PREFIX_OP;
+ break;
+
+ case 46:
+ case 47:
+ if (ppc_process_record_prefix_store_vsx_ds_form (gdbarch, regcache, addr,
+ insn_prefix, insn_suffix) != 0)
+ goto UNKNOWN_PREFIX_OP;
+ break;
+
+ case 56: /* Prefixed Load Quadword, plq */
+ {
+ if ((type == 0) && (ST1 == 0))
+ {
+ int tmp;
+ tmp = tdep->ppc_gp0_regnum + (PPC_RT (insn_suffix) & ~1);
+ record_full_arch_list_add_reg (regcache, tmp);
+ record_full_arch_list_add_reg (regcache, tmp + 1);
+ }
+ else
+ goto UNKNOWN_PREFIX_OP;
+ break;
+ }
+
+ case 41: /* Prefixed Load Word Algebraic, plwa */
+ case 57: /* Prefixed Load Doubleword, pld */
+ if ((type == 0) && (ST1 == 0))
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_gp0_regnum
+ + PPC_RT (insn_suffix));
+ else
+ goto UNKNOWN_PREFIX_OP;
+ break;
+
+ case 48: /* Prefixed Load Floating-Point Single, plfs */
+ case 50: /* Prefixed Load Floating-Point Double, plfd */
+ if ((type == 2) && (ST1 == 0))
+ record_full_arch_list_add_reg (regcache,
+ tdep->ppc_fp0_regnum
+ + PPC_FRT (insn_suffix));
+ else
+ goto UNKNOWN_PREFIX_OP;
+ break;
+
+ case 58: /* Prefixed Load VSX Vector Paired, plxvp */
+ if ((type == 0) && (ST1 == 0))
+ {
+ ppc_record_vsr (regcache, tdep, PPC_XTp (insn_suffix));
+ ppc_record_vsr (regcache, tdep, PPC_XTp (insn_suffix) + 1);
+ }
+ else
+ goto UNKNOWN_PREFIX_OP;
+ break;
+
+ case 59:
+ if (ppc_process_record_prefix_op59_XX3 (gdbarch, regcache, insn_prefix,
+ insn_suffix) != 0)
+ goto UNKNOWN_PREFIX_OP;
+ break;
+
+ case 62: /* Prefixed Store VSX Vector Paired 8LS, pstxvp */
+ if ((type == 0) && (ST1 == 0))
+ {
+ int R = PPC_BIT (insn_prefix, 11);
+ CORE_ADDR ea = 0;
+
+ if (R == 0)
+ {
+ if (PPC_RA (insn_suffix) != 0)
+ regcache_raw_read_unsigned (regcache,
+ tdep->ppc_gp0_regnum
+ + PPC_RA (insn_suffix), &ea);
+ }
+ else
+ {
+ ea = addr; /* PC relative */
+ }
+
+ ea += P_PPC_D (insn_prefix, insn_suffix) << 4;
+ record_full_arch_list_add_mem (ea, 32);
+ }
+ else
+ goto UNKNOWN_PREFIX_OP;
+ break;
+
+ default:
+UNKNOWN_PREFIX_OP:
+ gdb_printf (gdb_stdlog,
+ "Warning: Don't know how to record prefix instruction "
+ "%08x %08x at %s, %d.\n",
+ insn_prefix, insn_suffix, paddress (gdbarch, addr),
+ op6);
+ return -1;
+ }
+
+ SUCCESS:
+ if (record_full_arch_list_add_reg (regcache, PPC_PC_REGNUM))
+ return -1;
+
+ if (record_full_arch_list_add_end ())
+ return -1;
+ return 0;
+}
+
+int
+ppc_process_record (struct gdbarch *gdbarch, struct regcache *regcache,
+ CORE_ADDR addr)
+{
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ uint32_t insn, insn_suffix;
+ int op6, tmp, i;
insn = read_memory_unsigned_integer (addr, 4, byte_order);
op6 = PPC_OP6 (insn);
switch (op6)
{
+ case 1: /* prefixed instruction */
+ {
+ /* Get the lower 32-bits of the prefixed instruction. */
+ insn_suffix = read_memory_unsigned_integer (addr+4, 4, byte_order);
+ return ppc_process_prefix_instruction (insn, insn_suffix, addr,
+ gdbarch, regcache);
+ }
case 2: /* Trap Doubleword Immediate */
case 3: /* Trap Word Immediate */
/* Do nothing. */
break;
- case 4:
+ case 4: /* Vector Integer, Compare, Logical, Shift, etc. */
if (ppc_process_record_op4 (gdbarch, regcache, addr, insn) != 0)
return -1;
break;
+ case 6: /* Vector Load and Store */
+ if (ppc_process_record_op6 (gdbarch, regcache, addr, insn) != 0)
+ return -1;
+ break;
+
case 17: /* System call */
if (PPC_LEV (insn) != 0)
goto UNKNOWN_OP;
}
else
{
- printf_unfiltered (_("no syscall record support\n"));
+ gdb_printf (gdb_stderr, _("no syscall record support\n"));
return -1;
}
break;
case 47: /* Store Multiple Word */
{
- ULONGEST addr = 0;
+ ULONGEST iaddr = 0;
if (PPC_RA (insn) != 0)
regcache_raw_read_unsigned (regcache,
tdep->ppc_gp0_regnum + PPC_RA (insn),
- &addr);
+ &iaddr);
- addr += PPC_D (insn);
- record_full_arch_list_add_mem (addr, 4 * (32 - PPC_RS (insn)));
+ iaddr += PPC_D (insn);
+ record_full_arch_list_add_mem (iaddr, 4 * (32 - PPC_RS (insn)));
}
break;
case 52: /* Store Floating-Point Single */
case 54: /* Store Floating-Point Double */
{
- ULONGEST addr = 0;
+ ULONGEST iaddr = 0;
int size = -1;
if (PPC_RA (insn) != 0)
regcache_raw_read_unsigned (regcache,
tdep->ppc_gp0_regnum + PPC_RA (insn),
- &addr);
- addr += PPC_D (insn);
+ &iaddr);
+ iaddr += PPC_D (insn);
if (op6 == 36 || op6 == 37 || op6 == 52 || op6 == 53)
size = 4;
else
gdb_assert (0);
- record_full_arch_list_add_mem (addr, size);
+ record_full_arch_list_add_mem (iaddr, size);
}
break;
case 57:
switch (insn & 0x3)
- {
+ {
case 0: /* Load Floating-Point Double Pair */
tmp = tdep->ppc_fp0_regnum + (PPC_RT (insn) & ~1);
record_full_arch_list_add_reg (regcache, tmp);
/* Store Doubleword with Update */
/* Store Quadword with Update */
{
- ULONGEST addr = 0;
+ ULONGEST iaddr = 0;
int size;
int sub2 = PPC_FIELD (insn, 30, 2);
if (PPC_RA (insn) != 0)
regcache_raw_read_unsigned (regcache,
tdep->ppc_gp0_regnum + PPC_RA (insn),
- &addr);
+ &iaddr);
size = (sub2 == 2) ? 16 : 8;
- addr += PPC_DS (insn) << 2;
- record_full_arch_list_add_mem (addr, size);
+ iaddr += PPC_DS (insn) << 2;
+ record_full_arch_list_add_mem (iaddr, size);
if (op6 == 62 && sub2 == 1)
record_full_arch_list_add_reg (regcache,
default:
UNKNOWN_OP:
- fprintf_unfiltered (gdb_stdlog, "Warning: Don't know how to record %08x "
- "at %s, %d.\n", insn, paddress (gdbarch, addr), op6);
+ gdb_printf (gdb_stdlog, "Warning: Don't know how to record %08x "
+ "at %s, %d.\n", insn, paddress (gdbarch, addr), op6);
return -1;
}
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;
+}
+
+/* Implement the update_call_site_pc arch hook. */
+
+static CORE_ADDR
+ppc64_update_call_site_pc (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+ /* Some versions of GCC emit:
+
+ . bl function
+ . nop
+ . ...
+
+ but emit DWARF where the DW_AT_call_return_pc points to
+ instruction after the 'nop'. Note that while the compiler emits
+ a 'nop', the linker might put some other instruction there -- so
+ we just unconditionally check the next instruction. */
+ return pc + 4;
+}
+
/* 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.
static struct gdbarch *
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;
enum powerpc_long_double_abi long_double_abi = POWERPC_LONG_DOUBLE_AUTO;
enum powerpc_vector_abi vector_abi = powerpc_vector_abi_global;
enum powerpc_elf_abi elf_abi = POWERPC_ELF_AUTO;
- int have_fpu = 1, have_spe = 0, have_mq = 0, have_altivec = 0, have_dfp = 0,
- have_vsx = 0;
+ int have_fpu = 0, have_spe = 0, have_mq = 0, have_altivec = 0;
+ int have_dfp = 0, have_vsx = 0, have_ppr = 0, have_dscr = 0;
+ int have_tar = 0, have_ebb = 0, have_pmu = 0, have_htm_spr = 0;
+ int have_htm_core = 0, have_htm_fpu = 0, have_htm_altivec = 0;
+ int have_htm_vsx = 0, have_htm_ppr = 0, have_htm_dscr = 0;
+ int have_htm_tar = 0;
int tdesc_wordsize = -1;
const struct target_desc *tdesc = info.target_desc;
- struct tdesc_arch_data *tdesc_data = NULL;
+ tdesc_arch_data_up tdesc_data;
int num_pseudoregs = 0;
int cur_reg;
- /* INFO may refer to a binary that is not of the PowerPC architecture,
- e.g. when debugging a stand-alone SPE executable on a Cell/B.E. system.
- In this case, we must not attempt to infer properties of the (PowerPC
- side) of the target system from properties of that executable. Trust
- the target description instead. */
- if (info.abfd
- && bfd_get_arch (info.abfd) != bfd_arch_powerpc
- && bfd_get_arch (info.abfd) != bfd_arch_rs6000)
- info.abfd = NULL;
-
from_xcoff_exec = info.abfd && info.abfd->format == bfd_object &&
bfd_get_flavour (info.abfd) == bfd_target_xcoff_flavour;
layout, if we do not already have one. */
if (! tdesc_has_registers (tdesc))
{
- const struct variant *v;
+ const struct ppc_variant *v;
/* Choose variant. */
v = find_variant_by_arch (arch, mach);
valid_p = 1;
for (i = 0; i < ppc_num_gprs; i++)
- valid_p &= tdesc_numbered_register (feature, tdesc_data, i, gprs[i]);
- valid_p &= tdesc_numbered_register (feature, tdesc_data, PPC_PC_REGNUM,
- "pc");
- valid_p &= tdesc_numbered_register (feature, tdesc_data, PPC_LR_REGNUM,
- "lr");
- valid_p &= tdesc_numbered_register (feature, tdesc_data, PPC_XER_REGNUM,
- "xer");
-
- /* Allow alternate names for these registers, to accomodate GDB's
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ i, gprs[i]);
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_PC_REGNUM, "pc");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_LR_REGNUM, "lr");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_XER_REGNUM, "xer");
+
+ /* Allow alternate names for these registers, to accommodate GDB's
historic naming. */
- valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data.get (),
PPC_MSR_REGNUM, msr_names);
- valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data.get (),
PPC_CR_REGNUM, cr_names);
- valid_p &= tdesc_numbered_register_choices (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register_choices (feature, tdesc_data.get (),
PPC_CTR_REGNUM, ctr_names);
if (!valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
+ return NULL;
- have_mq = tdesc_numbered_register (feature, tdesc_data, PPC_MQ_REGNUM,
- "mq");
+ have_mq = tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_MQ_REGNUM, "mq");
tdesc_wordsize = tdesc_register_bitsize (feature, "pc") / 8;
if (wordsize == -1)
};
valid_p = 1;
for (i = 0; i < ppc_num_fprs; i++)
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
PPC_F0_REGNUM + i, fprs[i]);
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
PPC_FPSCR_REGNUM, "fpscr");
if (!valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
+ return NULL;
have_fpu = 1;
/* The fpscr register was expanded in isa 2.05 to 64 bits
valid_p = 1;
for (i = 0; i < ppc_num_gprs; i++)
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
PPC_VR0_REGNUM + i,
vector_regs[i]);
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
PPC_VSCR_REGNUM, "vscr");
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
PPC_VRSAVE_REGNUM, "vrsave");
if (have_spe || !valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
+ return NULL;
have_altivec = 1;
}
else
valid_p = 1;
for (i = 0; i < ppc_num_vshrs; i++)
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
PPC_VSR0_UPPER_REGNUM + i,
vsx_regs[i]);
- if (!valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
+
+ if (!valid_p || !have_fpu || !have_altivec)
+ return NULL;
have_vsx = 1;
}
valid_p = 1;
for (i = 0; i < ppc_num_gprs; i++)
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
PPC_SPE_UPPER_GP0_REGNUM + i,
upper_spe[i]);
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
PPC_SPE_ACC_REGNUM, "acc");
- valid_p &= tdesc_numbered_register (feature, tdesc_data,
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
PPC_SPE_FSCR_REGNUM, "spefscr");
if (have_mq || have_fpu || !valid_p)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
+ return NULL;
have_spe = 1;
}
else
have_spe = 0;
+
+ /* Program Priority Register. */
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.ppr");
+ if (feature != NULL)
+ {
+ valid_p = 1;
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_PPR_REGNUM, "ppr");
+
+ if (!valid_p)
+ return NULL;
+ have_ppr = 1;
+ }
+ else
+ have_ppr = 0;
+
+ /* Data Stream Control Register. */
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.dscr");
+ if (feature != NULL)
+ {
+ valid_p = 1;
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_DSCR_REGNUM, "dscr");
+
+ if (!valid_p)
+ return NULL;
+ have_dscr = 1;
+ }
+ else
+ have_dscr = 0;
+
+ /* Target Address Register. */
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.tar");
+ if (feature != NULL)
+ {
+ valid_p = 1;
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_TAR_REGNUM, "tar");
+
+ if (!valid_p)
+ return NULL;
+ have_tar = 1;
+ }
+ else
+ have_tar = 0;
+
+ /* Event-based Branching Registers. */
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.ebb");
+ if (feature != NULL)
+ {
+ static const char *const ebb_regs[] = {
+ "bescr", "ebbhr", "ebbrr"
+ };
+
+ valid_p = 1;
+ for (i = 0; i < ARRAY_SIZE (ebb_regs); i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_BESCR_REGNUM + i,
+ ebb_regs[i]);
+ if (!valid_p)
+ return NULL;
+ have_ebb = 1;
+ }
+ else
+ have_ebb = 0;
+
+ /* Subset of the ISA 2.07 Performance Monitor Registers provided
+ by Linux. */
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.linux.pmu");
+ if (feature != NULL)
+ {
+ valid_p = 1;
+
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_MMCR0_REGNUM,
+ "mmcr0");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_MMCR2_REGNUM,
+ "mmcr2");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_SIAR_REGNUM,
+ "siar");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_SDAR_REGNUM,
+ "sdar");
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_SIER_REGNUM,
+ "sier");
+
+ if (!valid_p)
+ return NULL;
+ have_pmu = 1;
+ }
+ else
+ have_pmu = 0;
+
+ /* Hardware Transactional Memory Registers. */
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.htm.spr");
+ if (feature != NULL)
+ {
+ static const char *const tm_spr_regs[] = {
+ "tfhar", "texasr", "tfiar"
+ };
+
+ valid_p = 1;
+ for (i = 0; i < ARRAY_SIZE (tm_spr_regs); i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_TFHAR_REGNUM + i,
+ tm_spr_regs[i]);
+ if (!valid_p)
+ return NULL;
+
+ have_htm_spr = 1;
+ }
+ else
+ have_htm_spr = 0;
+
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.htm.core");
+ if (feature != NULL)
+ {
+ static const char *const cgprs[] = {
+ "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
+ "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14",
+ "cr15", "cr16", "cr17", "cr18", "cr19", "cr20", "cr21",
+ "cr22", "cr23", "cr24", "cr25", "cr26", "cr27", "cr28",
+ "cr29", "cr30", "cr31", "ccr", "cxer", "clr", "cctr"
+ };
+
+ valid_p = 1;
+
+ for (i = 0; i < ARRAY_SIZE (cgprs); i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_CR0_REGNUM + i,
+ cgprs[i]);
+ if (!valid_p)
+ return NULL;
+
+ have_htm_core = 1;
+ }
+ else
+ have_htm_core = 0;
+
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.htm.fpu");
+ if (feature != NULL)
+ {
+ valid_p = 1;
+
+ static const char *const cfprs[] = {
+ "cf0", "cf1", "cf2", "cf3", "cf4", "cf5", "cf6", "cf7",
+ "cf8", "cf9", "cf10", "cf11", "cf12", "cf13", "cf14", "cf15",
+ "cf16", "cf17", "cf18", "cf19", "cf20", "cf21", "cf22",
+ "cf23", "cf24", "cf25", "cf26", "cf27", "cf28", "cf29",
+ "cf30", "cf31", "cfpscr"
+ };
+
+ for (i = 0; i < ARRAY_SIZE (cfprs); i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_CF0_REGNUM + i,
+ cfprs[i]);
+
+ if (!valid_p)
+ return NULL;
+ have_htm_fpu = 1;
+ }
+ else
+ have_htm_fpu = 0;
+
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.htm.altivec");
+ if (feature != NULL)
+ {
+ valid_p = 1;
+
+ static const char *const cvmx[] = {
+ "cvr0", "cvr1", "cvr2", "cvr3", "cvr4", "cvr5", "cvr6",
+ "cvr7", "cvr8", "cvr9", "cvr10", "cvr11", "cvr12", "cvr13",
+ "cvr14", "cvr15","cvr16", "cvr17", "cvr18", "cvr19", "cvr20",
+ "cvr21", "cvr22", "cvr23", "cvr24", "cvr25", "cvr26",
+ "cvr27", "cvr28", "cvr29", "cvr30", "cvr31", "cvscr",
+ "cvrsave"
+ };
+
+ for (i = 0; i < ARRAY_SIZE (cvmx); i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_CVR0_REGNUM + i,
+ cvmx[i]);
+
+ if (!valid_p)
+ return NULL;
+ have_htm_altivec = 1;
+ }
+ else
+ have_htm_altivec = 0;
+
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.htm.vsx");
+ if (feature != NULL)
+ {
+ valid_p = 1;
+
+ static const char *const cvsx[] = {
+ "cvs0h", "cvs1h", "cvs2h", "cvs3h", "cvs4h", "cvs5h",
+ "cvs6h", "cvs7h", "cvs8h", "cvs9h", "cvs10h", "cvs11h",
+ "cvs12h", "cvs13h", "cvs14h", "cvs15h", "cvs16h", "cvs17h",
+ "cvs18h", "cvs19h", "cvs20h", "cvs21h", "cvs22h", "cvs23h",
+ "cvs24h", "cvs25h", "cvs26h", "cvs27h", "cvs28h", "cvs29h",
+ "cvs30h", "cvs31h"
+ };
+
+ for (i = 0; i < ARRAY_SIZE (cvsx); i++)
+ valid_p &= tdesc_numbered_register (feature, tdesc_data.get (),
+ (PPC_CVSR0_UPPER_REGNUM
+ + i),
+ cvsx[i]);
+
+ if (!valid_p || !have_htm_fpu || !have_htm_altivec)
+ return NULL;
+ have_htm_vsx = 1;
+ }
+ else
+ have_htm_vsx = 0;
+
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.htm.ppr");
+ if (feature != NULL)
+ {
+ valid_p = tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_CPPR_REGNUM, "cppr");
+
+ if (!valid_p)
+ return NULL;
+ have_htm_ppr = 1;
+ }
+ else
+ have_htm_ppr = 0;
+
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.htm.dscr");
+ if (feature != NULL)
+ {
+ valid_p = tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_CDSCR_REGNUM, "cdscr");
+
+ if (!valid_p)
+ return NULL;
+ have_htm_dscr = 1;
+ }
+ else
+ have_htm_dscr = 0;
+
+ feature = tdesc_find_feature (tdesc,
+ "org.gnu.gdb.power.htm.tar");
+ if (feature != NULL)
+ {
+ valid_p = tdesc_numbered_register (feature, tdesc_data.get (),
+ PPC_CTAR_REGNUM, "ctar");
+
+ if (!valid_p)
+ return NULL;
+ have_htm_tar = 1;
+ }
+ else
+ have_htm_tar = 0;
}
/* If we have a 64-bit binary on a 32-bit target, complain. Also
supplies a 64-bit description while debugging a 32-bit
binary. */
if (tdesc_wordsize != -1 && tdesc_wordsize != wordsize)
- {
- tdesc_data_cleanup (tdesc_data);
- return NULL;
- }
+ return NULL;
#ifdef HAVE_ELF
if (from_elf_exec)
if (elf_abi == POWERPC_ELF_AUTO)
{
if (wordsize == 8 && info.byte_order == BFD_ENDIAN_LITTLE)
- elf_abi = POWERPC_ELF_V2;
+ elf_abi = POWERPC_ELF_V2;
else
- elf_abi = POWERPC_ELF_V1;
+ elf_abi = POWERPC_ELF_V1;
}
if (soft_float_flag == AUTO_BOOLEAN_TRUE)
arches = gdbarch_list_lookup_by_info (arches->next, &info))
{
/* 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);
+ meaningful, because 64-bit CPUs can run in 32-bit mode. So, perform
+ separate word size check. */
+ ppc_gdbarch_tdep *tdep
+ = gdbarch_tdep<ppc_gdbarch_tdep> (arches->gdbarch);
if (tdep && tdep->elf_abi != elf_abi)
continue;
if (tdep && tdep->soft_float != soft_float)
if (tdep && tdep->vector_abi != vector_abi)
continue;
if (tdep && tdep->wordsize == wordsize)
- {
- if (tdesc_data != NULL)
- tdesc_data_cleanup (tdesc_data);
- return arches->gdbarch;
- }
+ return arches->gdbarch;
}
/* None found, create a new architecture from INFO, whose bfd_arch_info
- "set arch" trust blindly
- GDB startup useless but harmless */
- tdep = XCNEW (struct gdbarch_tdep);
+ gdbarch *gdbarch
+ = gdbarch_alloc (&info, gdbarch_tdep_up (new ppc_gdbarch_tdep));
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
+
tdep->wordsize = wordsize;
tdep->elf_abi = elf_abi;
tdep->soft_float = soft_float;
tdep->long_double_abi = long_double_abi;
tdep->vector_abi = vector_abi;
- gdbarch = gdbarch_alloc (&info, tdep);
-
tdep->ppc_gp0_regnum = PPC_R0_REGNUM;
tdep->ppc_toc_regnum = PPC_R0_REGNUM + 2;
tdep->ppc_ps_regnum = PPC_MSR_REGNUM;
tdep->ppc_ev0_upper_regnum = have_spe ? PPC_SPE_UPPER_GP0_REGNUM : -1;
tdep->ppc_acc_regnum = have_spe ? PPC_SPE_ACC_REGNUM : -1;
tdep->ppc_spefscr_regnum = have_spe ? PPC_SPE_FSCR_REGNUM : -1;
+ tdep->ppc_ppr_regnum = have_ppr ? PPC_PPR_REGNUM : -1;
+ tdep->ppc_dscr_regnum = have_dscr ? PPC_DSCR_REGNUM : -1;
+ tdep->ppc_tar_regnum = have_tar ? PPC_TAR_REGNUM : -1;
+ tdep->have_ebb = have_ebb;
+
+ /* If additional pmu registers are added, care must be taken when
+ setting new fields in the tdep below, to maintain compatibility
+ with features that only provide some of the registers. Currently
+ gdb access to the pmu registers is only supported in linux, and
+ linux only provides a subset of the pmu registers defined in the
+ architecture. */
+
+ tdep->ppc_mmcr0_regnum = have_pmu ? PPC_MMCR0_REGNUM : -1;
+ tdep->ppc_mmcr2_regnum = have_pmu ? PPC_MMCR2_REGNUM : -1;
+ tdep->ppc_siar_regnum = have_pmu ? PPC_SIAR_REGNUM : -1;
+ tdep->ppc_sdar_regnum = have_pmu ? PPC_SDAR_REGNUM : -1;
+ tdep->ppc_sier_regnum = have_pmu ? PPC_SIER_REGNUM : -1;
+
+ tdep->have_htm_spr = have_htm_spr;
+ tdep->have_htm_core = have_htm_core;
+ tdep->have_htm_fpu = have_htm_fpu;
+ tdep->have_htm_altivec = have_htm_altivec;
+ tdep->have_htm_vsx = have_htm_vsx;
+ tdep->ppc_cppr_regnum = have_htm_ppr ? PPC_CPPR_REGNUM : -1;
+ tdep->ppc_cdscr_regnum = have_htm_dscr ? PPC_CDSCR_REGNUM : -1;
+ tdep->ppc_ctar_regnum = have_htm_tar ? PPC_CTAR_REGNUM : -1;
set_gdbarch_pc_regnum (gdbarch, PPC_PC_REGNUM);
set_gdbarch_sp_regnum (gdbarch, PPC_R0_REGNUM + 1);
set_gdbarch_ps_regnum (gdbarch, tdep->ppc_ps_regnum);
if (wordsize == 8)
- set_gdbarch_return_value (gdbarch, ppc64_sysv_abi_return_value);
+ {
+ set_gdbarch_return_value (gdbarch, ppc64_sysv_abi_return_value);
+ set_gdbarch_update_call_site_pc (gdbarch, ppc64_update_call_site_pc);
+ }
else
set_gdbarch_return_value (gdbarch, ppc_sysv_abi_return_value);
+ set_gdbarch_get_return_buf_addr (gdbarch, ppc_sysv_get_return_buf_addr);
/* Set lr_frame_offset. */
if (wordsize == 8)
else
tdep->lr_frame_offset = 4;
- if (have_spe || have_dfp || have_vsx)
+ if (have_spe || have_dfp || have_altivec
+ || have_vsx || have_htm_fpu || have_htm_vsx)
{
set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch,
num_pseudoregs += 32;
if (have_dfp)
num_pseudoregs += 16;
+ if (have_altivec)
+ num_pseudoregs += 32;
if (have_vsx)
/* Include both VSX and Extended FP registers. */
num_pseudoregs += 96;
+ if (have_htm_fpu)
+ num_pseudoregs += 16;
+ /* Include both checkpointed VSX and EFP registers. */
+ if (have_htm_vsx)
+ num_pseudoregs += 64 + 32;
set_gdbarch_num_pseudo_regs (gdbarch, num_pseudoregs);
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_hw_singlestep (gdbarch,
ppc_displaced_step_hw_singlestep);
set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup);
- set_gdbarch_displaced_step_location (gdbarch,
- displaced_step_at_entry_point);
+ set_gdbarch_displaced_step_prepare (gdbarch, ppc_displaced_step_prepare);
+ set_gdbarch_displaced_step_finish (gdbarch, ppc_displaced_step_finish);
+ set_gdbarch_displaced_step_restore_all_in_ptid
+ (gdbarch, ppc_displaced_step_restore_all_in_ptid);
+ set_gdbarch_displaced_step_buffer_length (gdbarch, 2 * PPC_INSN_SIZE);
set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE);
/* Hook in ABI-specific overrides, if they have been registered. */
info.target_desc = tdesc;
- info.tdesc_data = tdesc_data;
+ info.tdesc_data = tdesc_data.get ();
gdbarch_init_osabi (info, gdbarch);
switch (info.osabi)
case GDB_OSABI_LINUX:
case GDB_OSABI_NETBSD:
case GDB_OSABI_UNKNOWN:
- set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc);
frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind);
frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind);
- set_gdbarch_dummy_id (gdbarch, rs6000_dummy_id);
frame_base_append_sniffer (gdbarch, rs6000_frame_base_sniffer);
break;
default:
set_gdbarch_believe_pcc_promotion (gdbarch, 1);
- set_gdbarch_unwind_pc (gdbarch, rs6000_unwind_pc);
frame_unwind_append_unwinder (gdbarch, &rs6000_epilogue_frame_unwind);
frame_unwind_append_unwinder (gdbarch, &rs6000_frame_unwind);
- set_gdbarch_dummy_id (gdbarch, rs6000_dummy_id);
frame_base_append_sniffer (gdbarch, rs6000_frame_base_sniffer);
}
set_tdesc_pseudo_register_type (gdbarch, rs6000_pseudo_register_type);
set_tdesc_pseudo_register_reggroup_p (gdbarch,
rs6000_pseudo_register_reggroup_p);
- tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+ tdesc_use_registers (gdbarch, tdesc, std::move (tdesc_data));
/* Override the normal target description method to make the SPE upper
halves anonymous. */
/* Choose register numbers for all supported pseudo-registers. */
tdep->ppc_ev0_regnum = -1;
tdep->ppc_dl0_regnum = -1;
+ tdep->ppc_v0_alias_regnum = -1;
tdep->ppc_vsr0_regnum = -1;
tdep->ppc_efpr0_regnum = -1;
+ tdep->ppc_cdl0_regnum = -1;
+ tdep->ppc_cvsr0_regnum = -1;
+ tdep->ppc_cefpr0_regnum = -1;
cur_reg = gdbarch_num_regs (gdbarch);
tdep->ppc_dl0_regnum = cur_reg;
cur_reg += 16;
}
+ if (have_altivec)
+ {
+ tdep->ppc_v0_alias_regnum = cur_reg;
+ cur_reg += 32;
+ }
if (have_vsx)
{
tdep->ppc_vsr0_regnum = cur_reg;
tdep->ppc_efpr0_regnum = cur_reg;
cur_reg += 32;
}
+ if (have_htm_fpu)
+ {
+ tdep->ppc_cdl0_regnum = cur_reg;
+ cur_reg += 16;
+ }
+ if (have_htm_vsx)
+ {
+ tdep->ppc_cvsr0_regnum = cur_reg;
+ cur_reg += 64;
+ tdep->ppc_cefpr0_regnum = cur_reg;
+ cur_reg += 32;
+ }
- gdb_assert (gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch) == cur_reg);
+ gdb_assert (gdbarch_num_cooked_regs (gdbarch) == cur_reg);
/* Register the ravenscar_arch_ops. */
if (mach == bfd_mach_ppc_e500)
static void
rs6000_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ppc_gdbarch_tdep *tdep = gdbarch_tdep<ppc_gdbarch_tdep> (gdbarch);
if (tdep == NULL)
return;
/* FIXME: Dump gdbarch_tdep. */
}
-/* PowerPC-specific commands. */
-
-static void
-set_powerpc_command (const char *args, int from_tty)
-{
- printf_unfiltered (_("\
-\"set powerpc\" must be followed by an appropriate subcommand.\n"));
- help_list (setpowerpccmdlist, "set powerpc ", all_commands, gdb_stdout);
-}
-
-static void
-show_powerpc_command (const char *args, int from_tty)
-{
- cmd_show_list (showpowerpccmdlist, from_tty, "");
-}
-
static void
powerpc_set_soft_float (const char *args, int from_tty,
struct cmd_list_element *c)
struct gdbarch_info info;
/* Update the architecture. */
- gdbarch_info_init (&info);
if (!gdbarch_update_p (info))
- internal_error (__FILE__, __LINE__, _("could not update architecture"));
+ internal_error (_("could not update architecture"));
}
static void
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;
}
if (vector_abi == POWERPC_VEC_LAST)
- internal_error (__FILE__, __LINE__, _("Invalid vector ABI accepted: %s."),
+ internal_error (_("Invalid vector ABI accepted: %s."),
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"));
+ internal_error (_("could not update architecture"));
}
/* Show the current setting of the exact watchpoints flag. */
struct cmd_list_element *c,
const char *value)
{
- fprintf_filtered (file, _("Use of exact watchpoints is %s.\n"), value);
+ gdb_printf (file, _("Use of exact watchpoints is %s.\n"), value);
}
/* Read a PPC instruction from memory. */
static unsigned int
-read_insn (struct frame_info *frame, CORE_ADDR pc)
+read_insn (frame_info_ptr frame, CORE_ADDR pc)
{
struct gdbarch *gdbarch = get_frame_arch (frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
necessarily the i'th instruction in memory. */
int
-ppc_insns_match_pattern (struct frame_info *frame, CORE_ADDR pc,
+ppc_insns_match_pattern (frame_info_ptr frame, CORE_ADDR pc,
const struct ppc_insn_pattern *pattern,
unsigned int *insns)
{
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 ();
void
-_initialize_rs6000_tdep (void)
+_initialize_rs6000_tdep ()
{
gdbarch_register (bfd_arch_rs6000, rs6000_gdbarch_init, rs6000_dump_tdep);
gdbarch_register (bfd_arch_powerpc, rs6000_gdbarch_init, rs6000_dump_tdep);
/* Add root prefix command for all "set powerpc"/"show powerpc"
commands. */
- add_prefix_cmd ("powerpc", no_class, set_powerpc_command,
- _("Various PowerPC-specific commands."),
- &setpowerpccmdlist, "set powerpc ", 0, &setlist);
-
- add_prefix_cmd ("powerpc", no_class, show_powerpc_command,
- _("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,