/* Target-dependent code for GDB, the GNU debugger.
- Copyright (C) 1986-2018 Free Software Foundation, Inc.
+ Copyright (C) 1986-2020 Free Software Foundation, Inc.
This file is part of GDB.
#include "infcall.h"
#include "sim-regno.h"
#include "gdb/sim-ppc.h"
+#include "reggroups.h"
#include "dwarf2-frame.h"
#include "target-descriptions.h"
#include "user-regs.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 \
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
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:
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;
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);
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))
{
|| IS_CDFP_PSEUDOREG (tdep, regnum))
/* PPC decimal128 pseudo-registers. */
return builtin_type (gdbarch)->builtin_declong;
+ 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. */
gdbarch_register_name (gdbarch, regnum), regnum);
}
+/* 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)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (IS_V_ALIAS_PSEUDOREG (tdep, regnum))
+ return 0;
+ else
+ return default_register_reggroup_p (gdbarch, regnum, group);
+}
+
/* The register format for RS/6000 floating point registers is always
double, we need a conversion if the memory format is float. */
}
}
+/* 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)
+{
+ struct gdbarch_tdep *tdep = 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)
+{
+ struct gdbarch_tdep *tdep = 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,
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_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_DFP_PSEUDOREG (tdep, reg_nr)
|| IS_CDFP_PSEUDOREG (tdep, reg_nr))
dfp_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+ 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);
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
+v_alias_pseudo_register_collect (struct gdbarch *gdbarch,
+ struct agent_expr *ax, int reg_nr)
+{
+ struct gdbarch_tdep *tdep = 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. */
{
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))
{
}
\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
{
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.
(*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. */
trad_frame_set_value (cache->saved_regs,
gdbarch_pc_regnum (gdbarch), 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;
}
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))
{
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;
else
tdep->lr_frame_offset = 4;
- if (have_spe || have_dfp || have_vsx || have_htm_fpu || have_htm_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;
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);
/* Override the normal target description method to make the SPE upper
/* 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_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;