6f072a1034
This patch defines pseudo-registers "v0" through "v31" as aliases that map to the corresponding raw "vr0" through "vr31" vector registers for Power. The motivation behind this is that although GDB defines these registers as "vrX", the disassembler prints them as "vX", e.g. as the operands in instructions such as "vaddubm v2,v1,v1". This can be confusing to users trying to print out the values of the operands while inspecting the disassembled code. The new aliases are made not to belong to any register group, to avoid duplicated values in "info register vector" and "info register all". The arch-specific rs6000_pseudo_register_reggroup_p function had previously been removed since the other pseudo-registers could have their groups inferred by their type. It restored with this patch to handle the aliases. Membership for the other pseudo-registers is still determined using the default function. A new tests checks that GDB prints the expected values of vector registers after they are filled by the inferior, by using both the raw names and the aliases. Two other existing tests are modified to also test the aliases. gdb/ChangeLog: 2019-01-14 Pedro Franco de Carvalho <pedromfc@linux.ibm.com> * ppc-tdep.h (struct gdbarch_tdep) <ppc_v0_alias_regnum>: New field. * rs6000-tdep.c: Include reggroups.h. (IS_V_ALIAS_PSEUDOREG): Define. (rs6000_register_name): Return names for the "vX" aliases. (rs6000_pseudo_register_type): Return type for the "vX" aliases. (rs6000_pseudo_register_reggroup_p): Restore. Handle "vX" aliases. Call default_register_reggroup_p for all other pseudo-registers. (v_alias_pseudo_register_read, v_alias_pseudo_register_write): New functions. (rs6000_pseudo_register_read, rs6000_pseudo_register_write): Handle "vX" aliases. (v_alias_pseudo_register_collect): New function. (rs6000_ax_pseudo_register_collect): Handle "vX" aliases. (rs6000_gdbarch_init): Initialize "vX" aliases as pseudo-registers. Restore registration of rs6000_pseudo_register_reggroup_p with set_tdesc_pseudo_register_reggroup_p. gdb/testsuite/ChangeLog: 2019-01-14 Pedro Franco de Carvalho <pedromfc@linux.ibm.com> * gdb.arch/vsx-regs.exp: Add tests that use the vector register aliases. * gdb.arch/altivec-regs.exp: Likewise. Fix indentation of two tests. * gdb.arch/powerpc-vector-regs.c: New file. * gdb.arch/powerpc-vector-regs.exp: New file. gdb/doc/ChangeLog: 2019-01-14 Pedro Franco de Carvalho <pedromfc@linux.ibm.com> * gdb.texinfo (PowerPC Features): Document the alias pseudo-registers for the org.gnu.gdb.power.altivec feature.
438 lines
14 KiB
C++
438 lines
14 KiB
C++
/* Target-dependent code for GDB, the GNU debugger.
|
|
|
|
Copyright (C) 2000-2019 Free Software Foundation, Inc.
|
|
|
|
This file is part of GDB.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifndef PPC_TDEP_H
|
|
#define PPC_TDEP_H
|
|
|
|
struct gdbarch;
|
|
struct frame_info;
|
|
struct value;
|
|
struct regcache;
|
|
struct type;
|
|
|
|
/* From ppc-sysv-tdep.c ... */
|
|
enum return_value_convention ppc_sysv_abi_return_value (struct gdbarch *gdbarch,
|
|
struct value *function,
|
|
struct type *valtype,
|
|
struct regcache *regcache,
|
|
gdb_byte *readbuf,
|
|
const gdb_byte *writebuf);
|
|
enum return_value_convention ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch,
|
|
struct value *function,
|
|
struct type *valtype,
|
|
struct regcache *regcache,
|
|
gdb_byte *readbuf,
|
|
const gdb_byte *writebuf);
|
|
|
|
CORE_ADDR ppc_sysv_abi_push_dummy_call
|
|
(struct gdbarch *gdbarch, struct value *function, struct regcache *regcache,
|
|
CORE_ADDR bp_addr, int nargs, struct value **args, CORE_ADDR sp,
|
|
function_call_return_method return_method, CORE_ADDR struct_addr);
|
|
|
|
CORE_ADDR ppc64_sysv_abi_push_dummy_call
|
|
(struct gdbarch *gdbarch, struct value *function, struct regcache *regcache,
|
|
CORE_ADDR bp_addr, int nargs, struct value **args, CORE_ADDR sp,
|
|
function_call_return_method return_method, CORE_ADDR struct_addr);
|
|
|
|
enum return_value_convention ppc64_sysv_abi_return_value (struct gdbarch *gdbarch,
|
|
struct value *function,
|
|
struct type *valtype,
|
|
struct regcache *regcache,
|
|
gdb_byte *readbuf,
|
|
const gdb_byte *writebuf);
|
|
|
|
/* From rs6000-tdep.c... */
|
|
int altivec_register_p (struct gdbarch *gdbarch, int regno);
|
|
int vsx_register_p (struct gdbarch *gdbarch, int regno);
|
|
int spe_register_p (struct gdbarch *gdbarch, int regno);
|
|
|
|
/* Return non-zero if the architecture described by GDBARCH has
|
|
floating-point registers (f0 --- f31 and fpscr). */
|
|
int ppc_floating_point_unit_p (struct gdbarch *gdbarch);
|
|
|
|
/* Return non-zero if the architecture described by GDBARCH has
|
|
Altivec registers (vr0 --- vr31, vrsave and vscr). */
|
|
int ppc_altivec_support_p (struct gdbarch *gdbarch);
|
|
|
|
/* Return non-zero if the architecture described by GDBARCH has
|
|
VSX registers (vsr0 --- vsr63). */
|
|
int vsx_support_p (struct gdbarch *gdbarch);
|
|
std::vector<CORE_ADDR> ppc_deal_with_atomic_sequence
|
|
(struct regcache *regcache);
|
|
|
|
|
|
/* Register set description. */
|
|
|
|
struct ppc_reg_offsets
|
|
{
|
|
/* General-purpose registers. */
|
|
int r0_offset;
|
|
int gpr_size; /* size for r0-31, pc, ps, lr, ctr. */
|
|
int xr_size; /* size for cr, xer, mq. */
|
|
int pc_offset;
|
|
int ps_offset;
|
|
int cr_offset;
|
|
int lr_offset;
|
|
int ctr_offset;
|
|
int xer_offset;
|
|
int mq_offset;
|
|
|
|
/* Floating-point registers. */
|
|
int f0_offset;
|
|
int fpscr_offset;
|
|
int fpscr_size;
|
|
};
|
|
|
|
extern void ppc_supply_reg (struct regcache *regcache, int regnum,
|
|
const gdb_byte *regs, size_t offset, int regsize);
|
|
|
|
extern void ppc_collect_reg (const struct regcache *regcache, int regnum,
|
|
gdb_byte *regs, size_t offset, int regsize);
|
|
|
|
/* Supply register REGNUM in the general-purpose register set REGSET
|
|
from the buffer specified by GREGS and LEN to register cache
|
|
REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
|
|
|
|
extern void ppc_supply_gregset (const struct regset *regset,
|
|
struct regcache *regcache,
|
|
int regnum, const void *gregs, size_t len);
|
|
|
|
/* Supply register REGNUM in the floating-point register set REGSET
|
|
from the buffer specified by FPREGS and LEN to register cache
|
|
REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
|
|
|
|
extern void ppc_supply_fpregset (const struct regset *regset,
|
|
struct regcache *regcache,
|
|
int regnum, const void *fpregs, size_t len);
|
|
|
|
/* Supply register REGNUM in the Altivec register set REGSET
|
|
from the buffer specified by VRREGS and LEN to register cache
|
|
REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
|
|
|
|
extern void ppc_supply_vrregset (const struct regset *regset,
|
|
struct regcache *regcache,
|
|
int regnum, const void *vrregs, size_t len);
|
|
|
|
/* Supply register REGNUM in the VSX register set REGSET
|
|
from the buffer specified by VSXREGS and LEN to register cache
|
|
REGCACHE. If REGNUM is -1, do this for all registers in REGSET. */
|
|
|
|
extern void ppc_supply_vsxregset (const struct regset *regset,
|
|
struct regcache *regcache,
|
|
int regnum, const void *vsxregs, size_t len);
|
|
|
|
/* Collect register REGNUM in the general-purpose register set
|
|
REGSET, from register cache REGCACHE into the buffer specified by
|
|
GREGS and LEN. If REGNUM is -1, do this for all registers in
|
|
REGSET. */
|
|
|
|
extern void ppc_collect_gregset (const struct regset *regset,
|
|
const struct regcache *regcache,
|
|
int regnum, void *gregs, size_t len);
|
|
|
|
/* Collect register REGNUM in the floating-point register set
|
|
REGSET, from register cache REGCACHE into the buffer specified by
|
|
FPREGS and LEN. If REGNUM is -1, do this for all registers in
|
|
REGSET. */
|
|
|
|
extern void ppc_collect_fpregset (const struct regset *regset,
|
|
const struct regcache *regcache,
|
|
int regnum, void *fpregs, size_t len);
|
|
|
|
/* Collect register REGNUM in the Altivec register set
|
|
REGSET from register cache REGCACHE into the buffer specified by
|
|
VRREGS and LEN. If REGNUM is -1, do this for all registers in
|
|
REGSET. */
|
|
|
|
extern void ppc_collect_vrregset (const struct regset *regset,
|
|
const struct regcache *regcache,
|
|
int regnum, void *vrregs, size_t len);
|
|
|
|
/* Collect register REGNUM in the VSX register set
|
|
REGSET from register cache REGCACHE into the buffer specified by
|
|
VSXREGS and LEN. If REGNUM is -1, do this for all registers in
|
|
REGSET. */
|
|
|
|
extern void ppc_collect_vsxregset (const struct regset *regset,
|
|
const struct regcache *regcache,
|
|
int regnum, void *vsxregs, size_t len);
|
|
|
|
/* Private data that this module attaches to struct gdbarch. */
|
|
|
|
/* ELF ABI version used by the inferior. */
|
|
enum powerpc_elf_abi
|
|
{
|
|
POWERPC_ELF_AUTO,
|
|
POWERPC_ELF_V1,
|
|
POWERPC_ELF_V2,
|
|
POWERPC_ELF_LAST
|
|
};
|
|
|
|
/* Vector ABI used by the inferior. */
|
|
enum powerpc_vector_abi
|
|
{
|
|
POWERPC_VEC_AUTO,
|
|
POWERPC_VEC_GENERIC,
|
|
POWERPC_VEC_ALTIVEC,
|
|
POWERPC_VEC_SPE,
|
|
POWERPC_VEC_LAST
|
|
};
|
|
|
|
/* long double ABI version used by the inferior. */
|
|
enum powerpc_long_double_abi
|
|
{
|
|
POWERPC_LONG_DOUBLE_AUTO,
|
|
POWERPC_LONG_DOUBLE_IBM128,
|
|
POWERPC_LONG_DOUBLE_IEEE128,
|
|
POWERPC_LONG_DOUBLE_LAST
|
|
};
|
|
|
|
struct gdbarch_tdep
|
|
{
|
|
int wordsize; /* Size in bytes of fixed-point word. */
|
|
int soft_float; /* Avoid FP registers for arguments? */
|
|
|
|
enum powerpc_elf_abi elf_abi; /* ELF ABI version. */
|
|
|
|
/* Format to use for the "long double" data type. */
|
|
enum powerpc_long_double_abi long_double_abi;
|
|
|
|
/* How to pass vector arguments. Never set to AUTO or LAST. */
|
|
enum powerpc_vector_abi vector_abi;
|
|
|
|
int ppc_gp0_regnum; /* GPR register 0 */
|
|
int ppc_toc_regnum; /* TOC register */
|
|
int ppc_ps_regnum; /* Processor (or machine) status (%msr) */
|
|
int ppc_cr_regnum; /* Condition register */
|
|
int ppc_lr_regnum; /* Link register */
|
|
int ppc_ctr_regnum; /* Count register */
|
|
int ppc_xer_regnum; /* Integer exception register */
|
|
|
|
/* Not all PPC and RS6000 variants will have the registers
|
|
represented below. A -1 is used to indicate that the register
|
|
is not present in this variant. */
|
|
|
|
/* Floating-point registers. */
|
|
int ppc_fp0_regnum; /* Floating-point register 0. */
|
|
int ppc_fpscr_regnum; /* fp status and condition register. */
|
|
|
|
/* Multiplier-Quotient Register (older POWER architectures only). */
|
|
int ppc_mq_regnum;
|
|
|
|
/* POWER7 VSX registers. */
|
|
int ppc_vsr0_regnum; /* First VSX register. */
|
|
int ppc_vsr0_upper_regnum; /* First right most dword vsx register. */
|
|
int ppc_efpr0_regnum; /* First Extended FP register. */
|
|
|
|
/* Altivec registers. */
|
|
int ppc_vr0_regnum; /* First AltiVec register. */
|
|
int ppc_vrsave_regnum; /* Last AltiVec register. */
|
|
|
|
/* Altivec pseudo-register vX aliases for the raw vrX
|
|
registers. */
|
|
int ppc_v0_alias_regnum;
|
|
|
|
/* SPE registers. */
|
|
int ppc_ev0_upper_regnum; /* First GPR upper half register. */
|
|
int ppc_ev0_regnum; /* First ev register. */
|
|
int ppc_acc_regnum; /* SPE 'acc' register. */
|
|
int ppc_spefscr_regnum; /* SPE 'spefscr' register. */
|
|
|
|
/* Program Priority Register. */
|
|
int ppc_ppr_regnum;
|
|
|
|
/* Data Stream Control Register. */
|
|
int ppc_dscr_regnum;
|
|
|
|
/* Target Address Register. */
|
|
int ppc_tar_regnum;
|
|
|
|
/* Decimal 128 registers. */
|
|
int ppc_dl0_regnum; /* First Decimal128 argument register pair. */
|
|
|
|
int have_ebb;
|
|
|
|
/* PMU registers. */
|
|
int ppc_mmcr0_regnum;
|
|
int ppc_mmcr2_regnum;
|
|
int ppc_siar_regnum;
|
|
int ppc_sdar_regnum;
|
|
int ppc_sier_regnum;
|
|
|
|
/* Hardware Transactional Memory registers. */
|
|
int have_htm_spr;
|
|
int have_htm_core;
|
|
int have_htm_fpu;
|
|
int have_htm_altivec;
|
|
int have_htm_vsx;
|
|
int ppc_cppr_regnum;
|
|
int ppc_cdscr_regnum;
|
|
int ppc_ctar_regnum;
|
|
|
|
/* HTM pseudo registers. */
|
|
int ppc_cdl0_regnum;
|
|
int ppc_cvsr0_regnum;
|
|
int ppc_cefpr0_regnum;
|
|
|
|
/* Offset to ABI specific location where link register is saved. */
|
|
int lr_frame_offset;
|
|
|
|
/* An array of integers, such that sim_regno[I] is the simulator
|
|
register number for GDB register number I, or -1 if the
|
|
simulator does not implement that register. */
|
|
int *sim_regno;
|
|
|
|
/* ISA-specific types. */
|
|
struct type *ppc_builtin_type_vec64;
|
|
struct type *ppc_builtin_type_vec128;
|
|
|
|
int (*ppc_syscall_record) (struct regcache *regcache);
|
|
};
|
|
|
|
|
|
/* Constants for register set sizes. */
|
|
enum
|
|
{
|
|
ppc_num_gprs = 32, /* 32 general-purpose registers. */
|
|
ppc_num_fprs = 32, /* 32 floating-point registers. */
|
|
ppc_num_srs = 16, /* 16 segment registers. */
|
|
ppc_num_vrs = 32, /* 32 Altivec vector registers. */
|
|
ppc_num_vshrs = 32, /* 32 doublewords (dword 1 of vs0~vs31). */
|
|
ppc_num_vsrs = 64, /* 64 VSX vector registers. */
|
|
ppc_num_efprs = 32 /* 32 Extended FP registers. */
|
|
};
|
|
|
|
|
|
/* Register number constants. These are GDB internal register
|
|
numbers; they are not used for the simulator or remote targets.
|
|
Extra SPRs (those other than MQ, CTR, LR, XER, SPEFSCR) are given
|
|
numbers above PPC_NUM_REGS. So are segment registers and other
|
|
target-defined registers. */
|
|
enum {
|
|
PPC_R0_REGNUM = 0,
|
|
PPC_F0_REGNUM = 32,
|
|
PPC_PC_REGNUM = 64,
|
|
PPC_MSR_REGNUM = 65,
|
|
PPC_CR_REGNUM = 66,
|
|
PPC_LR_REGNUM = 67,
|
|
PPC_CTR_REGNUM = 68,
|
|
PPC_XER_REGNUM = 69,
|
|
PPC_FPSCR_REGNUM = 70,
|
|
PPC_MQ_REGNUM = 71,
|
|
PPC_SPE_UPPER_GP0_REGNUM = 72,
|
|
PPC_SPE_ACC_REGNUM = 104,
|
|
PPC_SPE_FSCR_REGNUM = 105,
|
|
PPC_VR0_REGNUM = 106,
|
|
PPC_VSCR_REGNUM = 138,
|
|
PPC_VRSAVE_REGNUM = 139,
|
|
PPC_VSR0_UPPER_REGNUM = 140,
|
|
PPC_VSR31_UPPER_REGNUM = 171,
|
|
PPC_PPR_REGNUM = 172,
|
|
PPC_DSCR_REGNUM = 173,
|
|
PPC_TAR_REGNUM = 174,
|
|
|
|
/* EBB registers. */
|
|
PPC_BESCR_REGNUM = 175,
|
|
PPC_EBBHR_REGNUM = 176,
|
|
PPC_EBBRR_REGNUM = 177,
|
|
|
|
/* PMU registers. */
|
|
PPC_MMCR0_REGNUM = 178,
|
|
PPC_MMCR2_REGNUM = 179,
|
|
PPC_SIAR_REGNUM = 180,
|
|
PPC_SDAR_REGNUM = 181,
|
|
PPC_SIER_REGNUM = 182,
|
|
|
|
/* Hardware transactional memory registers. */
|
|
PPC_TFHAR_REGNUM = 183,
|
|
PPC_TEXASR_REGNUM = 184,
|
|
PPC_TFIAR_REGNUM = 185,
|
|
|
|
PPC_CR0_REGNUM = 186,
|
|
PPC_CCR_REGNUM = 218,
|
|
PPC_CXER_REGNUM = 219,
|
|
PPC_CLR_REGNUM = 220,
|
|
PPC_CCTR_REGNUM = 221,
|
|
|
|
PPC_CF0_REGNUM = 222,
|
|
PPC_CFPSCR_REGNUM = 254,
|
|
|
|
PPC_CVR0_REGNUM = 255,
|
|
PPC_CVSCR_REGNUM = 287,
|
|
PPC_CVRSAVE_REGNUM = 288,
|
|
|
|
PPC_CVSR0_UPPER_REGNUM = 289,
|
|
|
|
PPC_CPPR_REGNUM = 321,
|
|
PPC_CDSCR_REGNUM = 322,
|
|
PPC_CTAR_REGNUM = 323,
|
|
PPC_NUM_REGS
|
|
};
|
|
|
|
/* Big enough to hold the size of the largest register in bytes. */
|
|
#define PPC_MAX_REGISTER_SIZE 64
|
|
|
|
#define PPC_IS_EBB_REGNUM(i) \
|
|
((i) >= PPC_BESCR_REGNUM && (i) <= PPC_EBBRR_REGNUM)
|
|
|
|
#define PPC_IS_PMU_REGNUM(i) \
|
|
((i) >= PPC_MMCR0_REGNUM && (i) <= PPC_SIER_REGNUM)
|
|
|
|
#define PPC_IS_TMSPR_REGNUM(i) \
|
|
((i) >= PPC_TFHAR_REGNUM && (i) <= PPC_TFIAR_REGNUM)
|
|
|
|
#define PPC_IS_CKPTGP_REGNUM(i) \
|
|
((i) >= PPC_CR0_REGNUM && (i) <= PPC_CCTR_REGNUM)
|
|
|
|
#define PPC_IS_CKPTFP_REGNUM(i) \
|
|
((i) >= PPC_CF0_REGNUM && (i) <= PPC_CFPSCR_REGNUM)
|
|
|
|
#define PPC_IS_CKPTVMX_REGNUM(i) \
|
|
((i) >= PPC_CVR0_REGNUM && (i) <= PPC_CVRSAVE_REGNUM)
|
|
|
|
#define PPC_IS_CKPTVSX_REGNUM(i) \
|
|
((i) >= PPC_CVSR0_UPPER_REGNUM && (i) < (PPC_CVSR0_UPPER_REGNUM + 32))
|
|
|
|
/* An instruction to match. */
|
|
|
|
struct ppc_insn_pattern
|
|
{
|
|
unsigned int mask; /* mask the insn with this... */
|
|
unsigned int data; /* ...and see if it matches this. */
|
|
int optional; /* If non-zero, this insn may be absent. */
|
|
};
|
|
|
|
extern int ppc_insns_match_pattern (struct frame_info *frame, CORE_ADDR pc,
|
|
const struct ppc_insn_pattern *pattern,
|
|
unsigned int *insns);
|
|
extern CORE_ADDR ppc_insn_d_field (unsigned int insn);
|
|
|
|
extern CORE_ADDR ppc_insn_ds_field (unsigned int insn);
|
|
|
|
extern int ppc_process_record (struct gdbarch *gdbarch,
|
|
struct regcache *regcache, CORE_ADDR addr);
|
|
|
|
/* Instruction size. */
|
|
#define PPC_INSN_SIZE 4
|
|
|
|
/* Estimate for the maximum number of instrctions in a function epilogue. */
|
|
#define PPC_MAX_EPILOGUE_INSTRUCTIONS 52
|
|
|
|
#endif /* ppc-tdep.h */
|