From: Edjunior Barbosa Machado Date: Fri, 26 Oct 2018 12:37:55 +0000 (-0300) Subject: [PowerPC] Add support for HTM registers X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=8d619c01db64c533df3ffc706b694f293347f0d8;p=binutils-gdb.git [PowerPC] Add support for HTM registers This patch adds support for Hardware Transactional Memory registers for the powerpc linux native and core file targets, and for the pwoerpc linux server stub. These registers include both the HTM special-purpose registers (TFHAR, TEXASR and TFIAR) as well as the set of registers that are checkpointed (saved) when a transaction is initiated, which the processor restores in the event of a transaction failure. The set of checkpointed general-purpose registers is returned by the linux kernel in the same format as the regular general-purpose registers, defined in struct pt_regs. However, the architecture specifies that only some of the registers present in pt_regs are checkpointed (GPRs 0-31, CR, XER, LR and CTR). The kernel fills the slots for MSR and NIP with other info. The other fields usually don't have meaningful values. GDB doesn't define registers that are not checkpointed in the architecture, but when generating a core file, GDB fills the slot for the checkpointed MSR with the regular MSR. These are usually similar, although some bits might be different, and in some cases the checkpointed MSR will have a value of 0 in a kernel-generated core-file. The checkpointed NIP is filled with TFHAR by GDB in the core-file, which is what the kernel does. The other fields are set to 0 by GDB. Core files generated by the kernel have a note section for checkpointed GPRs with the same size for both 32-bit and 64-bit threads, and the values for the registers of a 32-bit thread are squeezed in the first half, with no useful data in the second half. GDB generates a smaller note section for 32-bit threads, but can read both sizes. The checkpointed XER is required to be 32-bit in the target description documentation, even though the more recent ISAs define it as 64-bit wide, since the high-order 32-bits are reserved, and because in Linux there is no way to get a 64-bit checkpointed XER for 32-bit threads. If this changes in the future, the target description feature requirement can be relaxed to allow for a 64-bit checkpointed XER. Access to the checkpointed CR (condition register) can be confusing. The architecture only specifies that CR fields 1 to 7 (the 24 least significant bits) are checkpointed, but the kernel provides all 8 fields (32 bits). The value of field 0 is not masked by ptrace, so it will sometimes show the result of some kernel operation, probably treclaim., which sets this field. The checkpointed registers are marked not to be saved and restored. Inferior function calls during an active transaction don't work well, and it's unclear what should be done in this case. TEXASR and TFIAR can be altered asynchronously, during transaction failure recording, so they are also not saved and restored. For consistency neither is TFHAR. Record and replay also doesn't work well when transactions are involved. This patch doesn't address this, so the values of the HTM SPRs will sometimes be innacurate when the record/relay target is enabled. For instance, executing a "tbegin." alters TFHAR and TEXASR, but these changes are not currently recorded. Because the checkpointed registers are only available when a transaction is active (or suspended), ptrace can return ENODATA when gdb tries to read these registers and the inferior is not in a transactional state. The registers are set to the unavailable state when this happens. When gbd tries to write to one of these registers, and it is unavailable, an error is raised. The "fill" functions for checkpointed register sets in the server stub are not implemented for the same reason as for the EBB register set, since ptrace can also return ENODATA for checkpointed regsets. The same issues with 'G' packets apply here. Just like for the EBB registers, tracepoints will not mark the checkpointed registers as unavailable if the inferior was not in a transaction, so their content will also show 0 instead of when inspecting trace data. The new tests record the values of the regular registers before stepping the inferior through a "tbegin." instruction to start a transaction, then the checkpointed registers are checked against the recorded pre-transactional values. New values are written to the checkpointed registers and recorded, the inferior continues until the transaction aborts (which is usually immediately when it is resumed), and the regular registers are checked against the recorded values, because the abort should have reverted the registers to these values. Like for the EBB registers, target_store_registers will ignore the checkpointed registers when called with -1 as the regno argument (store all registers in one go). gdb/ChangeLog: 2018-10-26 Edjunior Barbosa Machado Pedro Franco de Carvalho * arch/ppc-linux-tdesc.h (tdesc_powerpc_isa207_htm_vsx32l) (tdesc_powerpc_isa207_htm_vsx64l): Declare. * arch/ppc-linux-common.h (PPC_LINUX_SIZEOF_TM_SPRREGSET) (PPC32_LINUX_SIZEOF_CGPRREGSET, PPC64_LINUX_SIZEOF_CGPRREGSET) (PPC_LINUX_SIZEOF_CFPRREGSET, PPC_LINUX_SIZEOF_CVMXREGSET) (PPC_LINUX_SIZEOF_CVSXREGSET, PPC_LINUX_SIZEOF_CPPRREGSET) (PPC_LINUX_SIZEOF_CDSCRREGSET, PPC_LINUX_SIZEOF_CTARREGSET): Define. (struct ppc_linux_features) : New field. (ppc_linux_no_features): Add initializer for htm field. * arch/ppc-linux-common.c (ppc_linux_match_description): Return new tdescs. * nat/ppc-linux.h (PPC_FEATURE2_HTM, NT_PPC_TM_CGPR) (NT_PPC_TM_CFPR, NT_PPC_TM_CVMX, NT_PPC_TM_CVSX) (NT_PPC_TM_SPR, NT_PPC_TM_CTAR, NT_PPC_TM_CPPR, NT_PPC_TM_CDSCR): Define if not already defined. * features/Makefile (WHICH): Add rs6000/powerpc-isa207-htm-vsx32l and rs6000/powerpc-isa207-htm-vsx64l. (XMLTOC): Add rs6000/powerpc-isa207-htm-vsx32l.xml and rs6000/powerpc-isa207-htm-vsx64l.xml. * features/rs6000/power-htm-spr.xml: New file. * features/rs6000/power-htm-core.xml: New file. * features/rs6000/power64-htm-core.xml: New file. * features/rs6000/power-htm-fpu.xml: New file. * features/rs6000/power-htm-altivec.xml: New file. * features/rs6000/power-htm-vsx.xml: New file. * features/rs6000/power-htm-ppr.xml: New file. * features/rs6000/power-htm-dscr.xml: New file. * features/rs6000/power-htm-tar.xml: New file. * features/rs6000/powerpc-isa207-htm-vsx32l.xml: New file. * features/rs6000/powerpc-isa207-htm-vsx64l.xml: New file. * features/rs6000/powerpc-isa207-htm-vsx32l.c: Generate. * features/rs6000/powerpc-isa207-htm-vsx64l.c: Generate. * regformats/rs6000/powerpc-isa207-htm-vsx32l.dat: Generate. * regformats/rs6000/powerpc-isa207-htm-vsx64l.dat: Generate. * ppc-linux-nat.c (fetch_register, fetch_ppc_registers): Call fetch_regset with HTM regsets. (store_register, store_ppc_registers): Call store_regset with HTM regsets. (ppc_linux_nat_target::read_description): Set htm field in the features struct if needed. * ppc-linux-tdep.c: Include features/rs6000/powerpc-isa207-htm-vsx32l.c and features/rs6000/powerpc-isa207-htm-vsx64l.c. (ppc32_regmap_tm_spr, ppc32_regmap_cgpr, ppc64_le_regmap_cgpr) (ppc64_be_regmap_cgpr, ppc32_regmap_cfpr, ppc32_le_regmap_cvmx) (ppc32_be_regmap_cvmx, ppc32_regmap_cvsx, ppc32_regmap_cppr) (ppc32_regmap_cdscr, ppc32_regmap_ctar): New globals. (ppc32_linux_tm_sprregset, ppc32_linux_cgprregset) (ppc64_be_linux_cgprregset, ppc64_le_linux_cgprregset) (ppc32_linux_cfprregset, ppc32_le_linux_cvmxregset) (ppc32_be_linux_cvmxregset, ppc32_linux_cvsxregset) (ppc32_linux_cpprregset, ppc32_linux_cdscrregset) (ppc32_linux_ctarregset): New globals. (ppc_linux_cgprregset, ppc_linux_cvmxregset): New functions. (ppc_linux_collect_core_cpgrregset): New function. (ppc_linux_iterate_over_regset_sections): Call back with the htm regsets. (ppc_linux_core_read_description): Check if the tm spr section is present and set htm in the features struct. (_initialize_ppc_linux_tdep): Call initialize_tdesc_powerpc_isa207_htm_vsx32l and initialize_tdesc_powerpc_isa207_htm_vsx64l. * ppc-linux-tdep.h (ppc_linux_cgprregset, ppc_linux_cvmxregset): Declare. (ppc32_linux_tm_sprregset, ppc32_linux_cfprregset) (ppc32_linux_cvsxregset, ppc32_linux_cpprregset) (ppc32_linux_cdscrregset, ppc32_linux_ctarregset): Declare. * ppc-tdep.h (struct gdbarch_tdep) : New fields. : Likewise. : Likewise. : Likewise. (enum) : New enum fields. : Likewise. : Likewise. : Likewise. : Likewise. : Likewise. : Likewise. (PPC_IS_TMSPR_REGNUM, PPC_IS_CKPTGP_REGNUM, PPC_IS_CKPTFP_REGNUM) (PPC_IS_CKPTVMX_REGNUM, PPC_IS_CKPTVSX_REGNUM): Define. * rs6000-tdep.c (IS_CDFP_PSEUDOREG, IS_CVSX_PSEUDOREG) (IS_CEFP_PSEUDOREG): Define. (rs6000_register_name): Hide the upper halves of checkpointed VSX registers. Return names for the checkpointed DFP, VSX, and EFP pseudo registers. (rs6000_pseudo_register_type): Remove initial assert and raise an internal error in the else clause instead. Return types for the checkpointed DFP, VSX, and EFP pseudo registers. (dfp_pseudo_register_read, dfp_pseudo_register_write): Handle checkpointed DFP pseudo registers. (vsx_pseudo_register_read, vsx_pseudo_register_write): Handle checkpointed VSX pseudo registers. (efp_pseudo_register_read, efp_pseudo_register_write): Rename from efpr_pseudo_register_read and efpr_pseudo_register_write. Handle checkpointed EFP pseudo registers. (rs6000_pseudo_register_read, rs6000_pseudo_register_write): Handle checkpointed DFP, VSX, and EFP registers. (dfp_ax_pseudo_register_collect, vsx_ax_pseudo_register_collect) (efp_ax_pseudo_register_collect): New functions. (rs6000_ax_pseudo_register_collect): Move DFP, VSX and EFP pseudo register logic to new functions. Handle checkpointed DFP, VSX, and EFP pseudo registers. (rs6000_gdbarch_init): Look for and validate the htm features. Include checkpointed DFP, VSX and EFP pseudo-registers. * NEWS: Mention access to PPR, DSCR, TAR, EBB/PMU registers and HTM registers. gdb/gdbserver/ChangeLog: 2018-10-26 Pedro Franco de Carvalho * configure.srv (ipa_ppc_linux_regobj): Add powerpc-isa207-htm-vsx32l-ipa.o and powerpc-isa207-htm-vsx64l-ipa.o. (powerpc*-*-linux*): Add powerpc-isa207-htm-vsx32l.o and powerpc-isa207-htm-vsx64l.o to srv_regobj. Add rs6000/power-htm-spr.xml, rs6000/power-htm-core.xml, rs6000/power64-htm-core.xml, rs6000/power-htm-fpu.xml, rs6000/power-htm-altivec.xml, rs6000/power-htm-vsx.xml, rs6000/power-htm-ppr.xml, rs6000/power-htm-dscr.xml, rs6000/power-htm-tar.xml, rs6000/powerpc-isa207-htm-vsx32l.xml, and rs6000/powerpc-isa207-htm-vsx64l.xml to srv_xmlfiles. * linux-ppc-tdesc-init.h (enum ppc_linux_tdesc) : New enum value. (init_registers_powerpc_isa207_htm_vsx32l) (init_registers_powerpc_isa207_htm_vsx64l): Declare. * linux-ppc-low.c (ppc_fill_tm_sprregset, ppc_store_tm_sprregset) (ppc_store_tm_cgprregset, ppc_store_tm_cfprregset) (ppc_store_tm_cvrregset, ppc_store_tm_cvsxregset) (ppc_store_tm_cpprregset, ppc_store_tm_cdscrregset) (ppc_store_tm_ctarregset): New functions. (ppc_regsets): Add entries for HTM regsets. (ppc_arch_setup): Set htm in features struct when needed. Set sizes for the HTM regsets. (ppc_get_ipa_tdesc_idx): Return PPC_TDESC_ISA207_HTM_VSX. (initialize_low_arch): Call init_registers_powerpc_isa207_htm_vsx32l and init_registers_powerpc_isa207_htm_vsx64l. * linux-ppc-ipa.c (get_ipa_tdesc): Handle PPC_TDESC_ISA207_HTM_VSX. (initialize_low_tracepoint): Call init_registers_powerpc_isa207_htm_vsx32l and init_registers_powerpc_isa207_htm_vsx64l. gdb/testsuite/ChangeLog: 2018-10-26 Pedro Franco de Carvalho * gdb.arch/powerpc-htm-regs.c: New file. * gdb.arch/powerpc-htm-regs.exp: New file. gdb/doc/ChangeLog: 2018-10-26 Pedro Franco de Carvalho * gdb.texinfo (PowerPC Features): Describe new features "org.gnu.gdb.power.htm.spr", "org.gnu.gdb.power.htm.core", "org.gnu.gdb.power.htm.fpu", "org.gnu.gdb.power.htm.altivec", "org.gnu.gdb.power.htm.vsx", "org.gnu.gdb.power.htm.ppr", "org.gnu.gdb.power.htm.dscr", "org.gnu.gdb.power.htm.tar". --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 74c7b396eba..4376263bbd2 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,118 @@ +2018-10-26 Edjunior Barbosa Machado + Pedro Franco de Carvalho + + * arch/ppc-linux-tdesc.h (tdesc_powerpc_isa207_htm_vsx32l) + (tdesc_powerpc_isa207_htm_vsx64l): Declare. + * arch/ppc-linux-common.h (PPC_LINUX_SIZEOF_TM_SPRREGSET) + (PPC32_LINUX_SIZEOF_CGPRREGSET, PPC64_LINUX_SIZEOF_CGPRREGSET) + (PPC_LINUX_SIZEOF_CFPRREGSET, PPC_LINUX_SIZEOF_CVMXREGSET) + (PPC_LINUX_SIZEOF_CVSXREGSET, PPC_LINUX_SIZEOF_CPPRREGSET) + (PPC_LINUX_SIZEOF_CDSCRREGSET, PPC_LINUX_SIZEOF_CTARREGSET): + Define. + (struct ppc_linux_features) : New field. + (ppc_linux_no_features): Add initializer for htm field. + * arch/ppc-linux-common.c (ppc_linux_match_description): Return + new tdescs. + * nat/ppc-linux.h (PPC_FEATURE2_HTM, NT_PPC_TM_CGPR) + (NT_PPC_TM_CFPR, NT_PPC_TM_CVMX, NT_PPC_TM_CVSX) + (NT_PPC_TM_SPR, NT_PPC_TM_CTAR, NT_PPC_TM_CPPR, NT_PPC_TM_CDSCR): + Define if not already defined. + * features/Makefile (WHICH): Add rs6000/powerpc-isa207-htm-vsx32l + and rs6000/powerpc-isa207-htm-vsx64l. + (XMLTOC): Add rs6000/powerpc-isa207-htm-vsx32l.xml and + rs6000/powerpc-isa207-htm-vsx64l.xml. + * features/rs6000/power-htm-spr.xml: New file. + * features/rs6000/power-htm-core.xml: New file. + * features/rs6000/power64-htm-core.xml: New file. + * features/rs6000/power-htm-fpu.xml: New file. + * features/rs6000/power-htm-altivec.xml: New file. + * features/rs6000/power-htm-vsx.xml: New file. + * features/rs6000/power-htm-ppr.xml: New file. + * features/rs6000/power-htm-dscr.xml: New file. + * features/rs6000/power-htm-tar.xml: New file. + * features/rs6000/powerpc-isa207-htm-vsx32l.xml: New file. + * features/rs6000/powerpc-isa207-htm-vsx64l.xml: New file. + * features/rs6000/powerpc-isa207-htm-vsx32l.c: Generate. + * features/rs6000/powerpc-isa207-htm-vsx64l.c: Generate. + * regformats/rs6000/powerpc-isa207-htm-vsx32l.dat: Generate. + * regformats/rs6000/powerpc-isa207-htm-vsx64l.dat: Generate. + * ppc-linux-nat.c (fetch_register, fetch_ppc_registers): Call + fetch_regset with HTM regsets. + (store_register, store_ppc_registers): Call store_regset with HTM + regsets. + (ppc_linux_nat_target::read_description): Set htm field in the + features struct if needed. + * ppc-linux-tdep.c: Include + features/rs6000/powerpc-isa207-htm-vsx32l.c and + features/rs6000/powerpc-isa207-htm-vsx64l.c. + (ppc32_regmap_tm_spr, ppc32_regmap_cgpr, ppc64_le_regmap_cgpr) + (ppc64_be_regmap_cgpr, ppc32_regmap_cfpr, ppc32_le_regmap_cvmx) + (ppc32_be_regmap_cvmx, ppc32_regmap_cvsx, ppc32_regmap_cppr) + (ppc32_regmap_cdscr, ppc32_regmap_ctar): New globals. + (ppc32_linux_tm_sprregset, ppc32_linux_cgprregset) + (ppc64_be_linux_cgprregset, ppc64_le_linux_cgprregset) + (ppc32_linux_cfprregset, ppc32_le_linux_cvmxregset) + (ppc32_be_linux_cvmxregset, ppc32_linux_cvsxregset) + (ppc32_linux_cpprregset, ppc32_linux_cdscrregset) + (ppc32_linux_ctarregset): New globals. + (ppc_linux_cgprregset, ppc_linux_cvmxregset): New functions. + (ppc_linux_collect_core_cpgrregset): New function. + (ppc_linux_iterate_over_regset_sections): Call back with the htm + regsets. + (ppc_linux_core_read_description): Check if the tm spr section is + present and set htm in the features struct. + (_initialize_ppc_linux_tdep): Call + initialize_tdesc_powerpc_isa207_htm_vsx32l and + initialize_tdesc_powerpc_isa207_htm_vsx64l. + * ppc-linux-tdep.h (ppc_linux_cgprregset, ppc_linux_cvmxregset): + Declare. + (ppc32_linux_tm_sprregset, ppc32_linux_cfprregset) + (ppc32_linux_cvsxregset, ppc32_linux_cpprregset) + (ppc32_linux_cdscrregset, ppc32_linux_ctarregset): Declare. + * ppc-tdep.h (struct gdbarch_tdep) : + New fields. + : + Likewise. + : Likewise. + : Likewise. + (enum) : + New enum fields. + : Likewise. + : Likewise. + : Likewise. + : Likewise. + : Likewise. + : Likewise. + (PPC_IS_TMSPR_REGNUM, PPC_IS_CKPTGP_REGNUM, PPC_IS_CKPTFP_REGNUM) + (PPC_IS_CKPTVMX_REGNUM, PPC_IS_CKPTVSX_REGNUM): Define. + * rs6000-tdep.c (IS_CDFP_PSEUDOREG, IS_CVSX_PSEUDOREG) + (IS_CEFP_PSEUDOREG): Define. + (rs6000_register_name): Hide the upper halves of checkpointed VSX + registers. Return names for the checkpointed DFP, VSX, and EFP + pseudo registers. + (rs6000_pseudo_register_type): Remove initial assert and raise an + internal error in the else clause instead. Return types for the + checkpointed DFP, VSX, and EFP pseudo registers. + (dfp_pseudo_register_read, dfp_pseudo_register_write): Handle + checkpointed DFP pseudo registers. + (vsx_pseudo_register_read, vsx_pseudo_register_write): Handle + checkpointed VSX pseudo registers. + (efp_pseudo_register_read, efp_pseudo_register_write): Rename + from efpr_pseudo_register_read and + efpr_pseudo_register_write. Handle checkpointed EFP pseudo + registers. + (rs6000_pseudo_register_read, rs6000_pseudo_register_write): + Handle checkpointed DFP, VSX, and EFP registers. + (dfp_ax_pseudo_register_collect, vsx_ax_pseudo_register_collect) + (efp_ax_pseudo_register_collect): New functions. + (rs6000_ax_pseudo_register_collect): Move DFP, VSX and EFP pseudo + register logic to new functions. Handle checkpointed DFP, VSX, + and EFP pseudo registers. + (rs6000_gdbarch_init): Look for and validate the htm features. + Include checkpointed DFP, VSX and EFP pseudo-registers. + * NEWS: Mention access to PPR, DSCR, TAR, EBB/PMU registers and + HTM registers. + 2018-10-26 Pedro Franco de Carvalho * rs6000-tdep.c (rs6000_gdbarch_init): Reject tdescs with vsx but diff --git a/gdb/NEWS b/gdb/NEWS index 6462e462e51..6b00cd8f9f0 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -3,6 +3,10 @@ *** Changes since GDB 8.2 +* GDB and GDBserver now support access to additional registers on + PowerPC GNU/Linux targets: PPR, DSCR, TAR, EBB/PMU registers, and + HTM registers. + * GDB now has experimental support for the compilation and injection of C++ source code into the inferior. This beta release does not include support for several language features, such as templates, constructors, diff --git a/gdb/arch/ppc-linux-common.c b/gdb/arch/ppc-linux-common.c index b8a7cdb2ad3..cc4d164320b 100644 --- a/gdb/arch/ppc-linux-common.c +++ b/gdb/arch/ppc-linux-common.c @@ -53,7 +53,8 @@ ppc_linux_match_description (struct ppc_linux_features features) if (features.cell) tdesc = tdesc_powerpc_cell64l; else if (features.vsx) - tdesc = (features.isa207? tdesc_powerpc_isa207_vsx64l + tdesc = (features.htm? tdesc_powerpc_isa207_htm_vsx64l + : features.isa207? tdesc_powerpc_isa207_vsx64l : features.ppr_dscr? tdesc_powerpc_isa205_ppr_dscr_vsx64l : features.isa205? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l); @@ -71,7 +72,8 @@ ppc_linux_match_description (struct ppc_linux_features features) if (features.cell) tdesc = tdesc_powerpc_cell32l; else if (features.vsx) - tdesc = (features.isa207? tdesc_powerpc_isa207_vsx32l + tdesc = (features.htm? tdesc_powerpc_isa207_htm_vsx32l + : features.isa207? tdesc_powerpc_isa207_vsx32l : features.ppr_dscr? tdesc_powerpc_isa205_ppr_dscr_vsx32l : features.isa205? tdesc_powerpc_isa205_vsx32l : tdesc_powerpc_vsx32l); diff --git a/gdb/arch/ppc-linux-common.h b/gdb/arch/ppc-linux-common.h index 50e9e064d0f..9ecb02bcf6a 100644 --- a/gdb/arch/ppc-linux-common.h +++ b/gdb/arch/ppc-linux-common.h @@ -35,6 +35,15 @@ struct target_desc; #define PPC_LINUX_SIZEOF_TARREGSET 8 #define PPC_LINUX_SIZEOF_EBBREGSET (3*8) #define PPC_LINUX_SIZEOF_PMUREGSET (5*8) +#define PPC_LINUX_SIZEOF_TM_SPRREGSET (3*8) +#define PPC32_LINUX_SIZEOF_CGPRREGSET (48*4) +#define PPC64_LINUX_SIZEOF_CGPRREGSET (48*8) +#define PPC_LINUX_SIZEOF_CFPRREGSET (32*8+8) +#define PPC_LINUX_SIZEOF_CVMXREGSET (34*16) +#define PPC_LINUX_SIZEOF_CVSXREGSET (32*8) +#define PPC_LINUX_SIZEOF_CPPRREGSET 8 +#define PPC_LINUX_SIZEOF_CDSCRREGSET 8 +#define PPC_LINUX_SIZEOF_CTARREGSET 8 /* Check if the hwcap auxv entry indicates that isa205 is supported. */ bool ppc_linux_has_isa205 (CORE_ADDR hwcap); @@ -48,6 +57,7 @@ struct ppc_linux_features bool isa205; bool ppr_dscr; bool isa207; + bool htm; bool cell; }; @@ -60,6 +70,7 @@ const struct ppc_linux_features ppc_linux_no_features = { false, false, false, + false, }; /* Return a target description that matches FEATURES. */ diff --git a/gdb/arch/ppc-linux-tdesc.h b/gdb/arch/ppc-linux-tdesc.h index 99628797866..2716be7e536 100644 --- a/gdb/arch/ppc-linux-tdesc.h +++ b/gdb/arch/ppc-linux-tdesc.h @@ -31,6 +31,7 @@ extern struct target_desc *tdesc_powerpc_isa205_altivec32l; extern struct target_desc *tdesc_powerpc_isa205_vsx32l; extern struct target_desc *tdesc_powerpc_isa205_ppr_dscr_vsx32l; extern struct target_desc *tdesc_powerpc_isa207_vsx32l; +extern struct target_desc *tdesc_powerpc_isa207_htm_vsx32l; extern struct target_desc *tdesc_powerpc_e500l; extern struct target_desc *tdesc_powerpc_64l; @@ -42,5 +43,6 @@ extern struct target_desc *tdesc_powerpc_isa205_altivec64l; extern struct target_desc *tdesc_powerpc_isa205_vsx64l; extern struct target_desc *tdesc_powerpc_isa205_ppr_dscr_vsx64l; extern struct target_desc *tdesc_powerpc_isa207_vsx64l; +extern struct target_desc *tdesc_powerpc_isa207_htm_vsx64l; #endif /* ARCH_PPC_LINUX_TDESC_H */ diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index ee5d23f5f58..abcdbda5d49 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,11 @@ +2018-10-26 Pedro Franco de Carvalho + + * gdb.texinfo (PowerPC Features): Describe new features + "org.gnu.gdb.power.htm.spr", "org.gnu.gdb.power.htm.core", + "org.gnu.gdb.power.htm.fpu", "org.gnu.gdb.power.htm.altivec", + "org.gnu.gdb.power.htm.vsx", "org.gnu.gdb.power.htm.ppr", + "org.gnu.gdb.power.htm.dscr", "org.gnu.gdb.power.htm.tar". + 2018-10-26 Pedro Franco de Carvalho * gdb.texinfo (PowerPC Features): Describe new features diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index e8130ce04a6..c49a7745f84 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -43210,6 +43210,48 @@ contain registers @samp{mmcr0}, @samp{mmcr2}, @samp{siar}, @samp{sdar} and @samp{sier}, all 64-bit wide. This is the subset of the isa 2.07 server PMU registers provided by @sc{gnu}/Linux. +The @samp{org.gnu.gdb.power.htm.spr} feature is optional. It should +contain registers @samp{tfhar}, @samp{texasr} and @samp{tfiar}, all +64-bit wide. + +The @samp{org.gnu.gdb.power.htm.core} feature is optional. It should +contain the checkpointed general-purpose registers @samp{cr0} through +@samp{cr31}, as well as the checkpointed registers @samp{clr} and +@samp{cctr}. These registers may all be either 32-bit or 64-bit +depending on the target. It should also contain the checkpointed +registers @samp{ccr} and @samp{cxer}, which should both be 32-bit +wide. + +The @samp{org.gnu.gdb.power.htm.fpu} feature is optional. It should +contain the checkpointed 64-bit floating-point registers @samp{cf0} +through @samp{cf31}, as well as the checkpointed 64-bit register +@samp{cfpscr}. + +The @samp{org.gnu.gdb.power.htm.altivec} feature is optional. It +should contain the checkpointed altivec registers @samp{cvr0} through +@samp{cvr31}, all 128-bit wide. It should also contain the +checkpointed registers @samp{cvscr} and @samp{cvrsave}, both 32-bit +wide. + +The @samp{org.gnu.gdb.power.htm.vsx} feature is optional. It should +contain registers @samp{cvs0h} through @samp{cvs31h}. @value{GDBN} +will combine these registers with the checkpointed floating point +registers (@samp{cf0} through @samp{cf31}) and the checkpointed +altivec registers (@samp{cvr0} through @samp{cvr31}) to present the +128-bit wide checkpointed vector-scalar registers @samp{cvs0} through +@samp{cvs63}. Therefore, this feature requires both +@samp{org.gnu.gdb.power.htm.altivec} and +@samp{org.gnu.gdb.power.htm.fpu}. + +The @samp{org.gnu.gdb.power.htm.ppr} feature is optional. It should +contain the 64-bit checkpointed register @samp{cppr}. + +The @samp{org.gnu.gdb.power.htm.dscr} feature is optional. It should +contain the 64-bit checkpointed register @samp{cdscr}. + +The @samp{org.gnu.gdb.power.htm.tar} feature is optional. It should +contain the 64-bit checkpointed register @samp{ctar}. + @node S/390 and System z Features @subsection S/390 and System z Features @cindex target descriptions, S/390 features diff --git a/gdb/features/Makefile b/gdb/features/Makefile index 6eaa7db05fd..150fef23f0b 100644 --- a/gdb/features/Makefile +++ b/gdb/features/Makefile @@ -76,6 +76,8 @@ WHICH = aarch64 \ rs6000/powerpc-isa205-ppr-dscr-vsx32l \ rs6000/powerpc-isa205-ppr-dscr-vsx64l \ rs6000/powerpc-isa207-vsx32l rs6000/powerpc-isa207-vsx64l \ + rs6000/powerpc-isa207-htm-vsx32l \ + rs6000/powerpc-isa207-htm-vsx64l \ s390-linux32 s390-linux64 s390x-linux64 \ s390-linux32v1 s390-linux64v1 s390x-linux64v1 \ s390-linux32v2 s390-linux64v2 s390x-linux64v2 \ @@ -174,6 +176,8 @@ XMLTOC = \ rs6000/powerpc-isa205-ppr-dscr-vsx64l.xml \ rs6000/powerpc-isa207-vsx32l.xml \ rs6000/powerpc-isa207-vsx64l.xml \ + rs6000/powerpc-isa207-htm-vsx32l.xml \ + rs6000/powerpc-isa207-htm-vsx64l.xml \ rs6000/powerpc-vsx32.xml \ rs6000/powerpc-vsx32l.xml \ rs6000/powerpc-vsx64.xml \ diff --git a/gdb/features/rs6000/power-htm-altivec.xml b/gdb/features/rs6000/power-htm-altivec.xml new file mode 100644 index 00000000000..efc33b7defa --- /dev/null +++ b/gdb/features/rs6000/power-htm-altivec.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb/features/rs6000/power-htm-core.xml b/gdb/features/rs6000/power-htm-core.xml new file mode 100644 index 00000000000..d067be842e2 --- /dev/null +++ b/gdb/features/rs6000/power-htm-core.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb/features/rs6000/power-htm-dscr.xml b/gdb/features/rs6000/power-htm-dscr.xml new file mode 100644 index 00000000000..9f218fadc68 --- /dev/null +++ b/gdb/features/rs6000/power-htm-dscr.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/gdb/features/rs6000/power-htm-fpu.xml b/gdb/features/rs6000/power-htm-fpu.xml new file mode 100644 index 00000000000..561a8c3c81c --- /dev/null +++ b/gdb/features/rs6000/power-htm-fpu.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb/features/rs6000/power-htm-ppr.xml b/gdb/features/rs6000/power-htm-ppr.xml new file mode 100644 index 00000000000..2725937b547 --- /dev/null +++ b/gdb/features/rs6000/power-htm-ppr.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/gdb/features/rs6000/power-htm-spr.xml b/gdb/features/rs6000/power-htm-spr.xml new file mode 100644 index 00000000000..e933439f1bb --- /dev/null +++ b/gdb/features/rs6000/power-htm-spr.xml @@ -0,0 +1,14 @@ + + + + + + + + + + diff --git a/gdb/features/rs6000/power-htm-tar.xml b/gdb/features/rs6000/power-htm-tar.xml new file mode 100644 index 00000000000..bc6339d4f78 --- /dev/null +++ b/gdb/features/rs6000/power-htm-tar.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/gdb/features/rs6000/power-htm-vsx.xml b/gdb/features/rs6000/power-htm-vsx.xml new file mode 100644 index 00000000000..2dd14fe1008 --- /dev/null +++ b/gdb/features/rs6000/power-htm-vsx.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb/features/rs6000/power64-htm-core.xml b/gdb/features/rs6000/power64-htm-core.xml new file mode 100644 index 00000000000..b8dd6aef593 --- /dev/null +++ b/gdb/features/rs6000/power64-htm-core.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb/features/rs6000/powerpc-isa207-htm-vsx32l.c b/gdb/features/rs6000/powerpc-isa207-htm-vsx32l.c new file mode 100644 index 00000000000..e1b933c8fb3 --- /dev/null +++ b/gdb/features/rs6000/powerpc-isa207-htm-vsx32l.c @@ -0,0 +1,396 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: powerpc-isa207-htm-vsx32l.xml */ + +#include "defs.h" +#include "osabi.h" +#include "target-descriptions.h" + +struct target_desc *tdesc_powerpc_isa207_htm_vsx32l; +static void +initialize_tdesc_powerpc_isa207_htm_vsx32l (void) +{ + struct target_desc *result = allocate_target_description (); + set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common")); + + struct tdesc_feature *feature; + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.core"); + tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "pc", 64, 1, NULL, 32, "code_ptr"); + tdesc_create_reg (feature, "msr", 65, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr", 66, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "lr", 67, 1, NULL, 32, "code_ptr"); + tdesc_create_reg (feature, "ctr", 68, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "xer", 69, 1, NULL, 32, "uint32"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.fpu"); + tdesc_create_reg (feature, "f0", 32, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f1", 33, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f2", 34, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f3", 35, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f4", 36, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f5", 37, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f6", 38, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f7", 39, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f8", 40, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f9", 41, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f10", 42, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f11", 43, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f12", 44, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f13", 45, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f14", 46, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f15", 47, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f16", 48, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f17", 49, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f18", 50, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f19", 51, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f20", 52, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f21", 53, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f22", 54, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f23", 55, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f24", 56, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f25", 57, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f26", 58, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f27", 59, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f28", 60, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f29", 61, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f30", 62, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f31", 63, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "fpscr", 70, 1, "float", 64, "int"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.linux"); + tdesc_create_reg (feature, "orig_r3", 71, 1, NULL, 32, "int"); + tdesc_create_reg (feature, "trap", 72, 1, NULL, 32, "int"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.altivec"); + tdesc_type *element_type; + element_type = tdesc_named_type (feature, "ieee_single"); + tdesc_create_vector (feature, "v4f", element_type, 4); + + element_type = tdesc_named_type (feature, "int32"); + tdesc_create_vector (feature, "v4i32", element_type, 4); + + element_type = tdesc_named_type (feature, "int16"); + tdesc_create_vector (feature, "v8i16", element_type, 8); + + element_type = tdesc_named_type (feature, "int8"); + tdesc_create_vector (feature, "v16i8", element_type, 16); + + tdesc_type_with_fields *type_with_fields; + type_with_fields = tdesc_create_union (feature, "vec128"); + tdesc_type *field_type; + field_type = tdesc_named_type (feature, "uint128"); + tdesc_add_field (type_with_fields, "uint128", field_type); + field_type = tdesc_named_type (feature, "v4f"); + tdesc_add_field (type_with_fields, "v4_float", field_type); + field_type = tdesc_named_type (feature, "v4i32"); + tdesc_add_field (type_with_fields, "v4_int32", field_type); + field_type = tdesc_named_type (feature, "v8i16"); + tdesc_add_field (type_with_fields, "v8_int16", field_type); + field_type = tdesc_named_type (feature, "v16i8"); + tdesc_add_field (type_with_fields, "v16_int8", field_type); + + tdesc_create_reg (feature, "vr0", 73, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr1", 74, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr2", 75, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr3", 76, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr4", 77, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr5", 78, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr6", 79, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr7", 80, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr8", 81, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr9", 82, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr10", 83, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr11", 84, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr12", 85, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr13", 86, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr14", 87, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr15", 88, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr16", 89, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr17", 90, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr18", 91, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr19", 92, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr20", 93, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr21", 94, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr22", 95, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr23", 96, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr24", 97, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr25", 98, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr26", 99, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr27", 100, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr28", 101, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr29", 102, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr30", 103, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr31", 104, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vscr", 105, 1, "vector", 32, "int"); + tdesc_create_reg (feature, "vrsave", 106, 1, "vector", 32, "int"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.vsx"); + tdesc_create_reg (feature, "vs0h", 107, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs1h", 108, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs2h", 109, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs3h", 110, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs4h", 111, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs5h", 112, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs6h", 113, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs7h", 114, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs8h", 115, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs9h", 116, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs10h", 117, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs11h", 118, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs12h", 119, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs13h", 120, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs14h", 121, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs15h", 122, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs16h", 123, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs17h", 124, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs18h", 125, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs19h", 126, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs20h", 127, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs21h", 128, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs22h", 129, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs23h", 130, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs24h", 131, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs25h", 132, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs26h", 133, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs27h", 134, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs28h", 135, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs29h", 136, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs30h", 137, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs31h", 138, 1, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.ppr"); + tdesc_create_reg (feature, "ppr", 139, 1, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.dscr"); + tdesc_create_reg (feature, "dscr", 140, 1, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.tar"); + tdesc_create_reg (feature, "tar", 141, 1, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.ebb"); + tdesc_create_reg (feature, "bescr", 142, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "ebbhr", 143, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "ebbrr", 144, 0, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.linux.pmu"); + tdesc_create_reg (feature, "mmcr0", 145, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "mmcr2", 146, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "siar", 147, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "sdar", 148, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "sier", 149, 0, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.spr"); + tdesc_create_reg (feature, "tfhar", 150, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "texasr", 151, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "tfiar", 152, 0, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.core"); + tdesc_create_reg (feature, "cr0", 153, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr1", 154, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr2", 155, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr3", 156, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr4", 157, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr5", 158, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr6", 159, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr7", 160, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr8", 161, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr9", 162, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr10", 163, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr11", 164, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr12", 165, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr13", 166, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr14", 167, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr15", 168, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr16", 169, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr17", 170, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr18", 171, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr19", 172, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr20", 173, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr21", 174, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr22", 175, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr23", 176, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr24", 177, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr25", 178, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr26", 179, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr27", 180, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr28", 181, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr29", 182, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr30", 183, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cr31", 184, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "ccr", 185, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cxer", 186, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "clr", 187, 0, NULL, 32, "code_ptr"); + tdesc_create_reg (feature, "cctr", 188, 0, NULL, 32, "uint32"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.fpu"); + tdesc_create_reg (feature, "cf0", 189, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf1", 190, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf2", 191, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf3", 192, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf4", 193, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf5", 194, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf6", 195, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf7", 196, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf8", 197, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf9", 198, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf10", 199, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf11", 200, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf12", 201, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf13", 202, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf14", 203, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf15", 204, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf16", 205, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf17", 206, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf18", 207, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf19", 208, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf20", 209, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf21", 210, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf22", 211, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf23", 212, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf24", 213, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf25", 214, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf26", 215, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf27", 216, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf28", 217, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf29", 218, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf30", 219, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf31", 220, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cfpscr", 221, 0, "float", 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.altivec"); + element_type = tdesc_named_type (feature, "ieee_single"); + tdesc_create_vector (feature, "v4f", element_type, 4); + + element_type = tdesc_named_type (feature, "int32"); + tdesc_create_vector (feature, "v4i32", element_type, 4); + + element_type = tdesc_named_type (feature, "int16"); + tdesc_create_vector (feature, "v8i16", element_type, 8); + + element_type = tdesc_named_type (feature, "int8"); + tdesc_create_vector (feature, "v16i8", element_type, 16); + + type_with_fields = tdesc_create_union (feature, "vec128"); + field_type = tdesc_named_type (feature, "uint128"); + tdesc_add_field (type_with_fields, "uint128", field_type); + field_type = tdesc_named_type (feature, "v4f"); + tdesc_add_field (type_with_fields, "v4_float", field_type); + field_type = tdesc_named_type (feature, "v4i32"); + tdesc_add_field (type_with_fields, "v4_int32", field_type); + field_type = tdesc_named_type (feature, "v8i16"); + tdesc_add_field (type_with_fields, "v8_int16", field_type); + field_type = tdesc_named_type (feature, "v16i8"); + tdesc_add_field (type_with_fields, "v16_int8", field_type); + + tdesc_create_reg (feature, "cvr0", 222, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr1", 223, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr2", 224, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr3", 225, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr4", 226, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr5", 227, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr6", 228, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr7", 229, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr8", 230, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr9", 231, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr10", 232, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr11", 233, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr12", 234, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr13", 235, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr14", 236, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr15", 237, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr16", 238, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr17", 239, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr18", 240, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr19", 241, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr20", 242, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr21", 243, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr22", 244, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr23", 245, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr24", 246, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr25", 247, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr26", 248, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr27", 249, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr28", 250, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr29", 251, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr30", 252, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr31", 253, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvscr", 254, 0, "vector", 32, "int"); + tdesc_create_reg (feature, "cvrsave", 255, 0, "vector", 32, "int"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.vsx"); + tdesc_create_reg (feature, "cvs0h", 256, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs1h", 257, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs2h", 258, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs3h", 259, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs4h", 260, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs5h", 261, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs6h", 262, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs7h", 263, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs8h", 264, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs9h", 265, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs10h", 266, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs11h", 267, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs12h", 268, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs13h", 269, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs14h", 270, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs15h", 271, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs16h", 272, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs17h", 273, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs18h", 274, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs19h", 275, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs20h", 276, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs21h", 277, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs22h", 278, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs23h", 279, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs24h", 280, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs25h", 281, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs26h", 282, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs27h", 283, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs28h", 284, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs29h", 285, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs30h", 286, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs31h", 287, 0, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.ppr"); + tdesc_create_reg (feature, "cppr", 288, 0, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.dscr"); + tdesc_create_reg (feature, "cdscr", 289, 0, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.tar"); + tdesc_create_reg (feature, "ctar", 290, 0, NULL, 64, "uint64"); + + tdesc_powerpc_isa207_htm_vsx32l = result; +} diff --git a/gdb/features/rs6000/powerpc-isa207-htm-vsx32l.xml b/gdb/features/rs6000/powerpc-isa207-htm-vsx32l.xml new file mode 100644 index 00000000000..6da85ad6289 --- /dev/null +++ b/gdb/features/rs6000/powerpc-isa207-htm-vsx32l.xml @@ -0,0 +1,29 @@ + + + + + + powerpc:common + + + + + + + + + + + + + + + + + + + diff --git a/gdb/features/rs6000/powerpc-isa207-htm-vsx64l.c b/gdb/features/rs6000/powerpc-isa207-htm-vsx64l.c new file mode 100644 index 00000000000..0d818d01593 --- /dev/null +++ b/gdb/features/rs6000/powerpc-isa207-htm-vsx64l.c @@ -0,0 +1,396 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: powerpc-isa207-htm-vsx64l.xml */ + +#include "defs.h" +#include "osabi.h" +#include "target-descriptions.h" + +struct target_desc *tdesc_powerpc_isa207_htm_vsx64l; +static void +initialize_tdesc_powerpc_isa207_htm_vsx64l (void) +{ + struct target_desc *result = allocate_target_description (); + set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64")); + + struct tdesc_feature *feature; + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.core"); + tdesc_create_reg (feature, "r0", 0, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r1", 1, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r2", 2, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r3", 3, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r4", 4, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r5", 5, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r6", 6, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r7", 7, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r11", 11, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r12", 12, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r16", 16, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r17", 17, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r18", 18, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r19", 19, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r20", 20, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r21", 21, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r22", 22, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r23", 23, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r24", 24, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r25", 25, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r26", 26, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r27", 27, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r28", 28, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r29", 29, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r30", 30, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "r31", 31, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "pc", 64, 1, NULL, 64, "code_ptr"); + tdesc_create_reg (feature, "msr", 65, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr", 66, 1, NULL, 32, "uint32"); + tdesc_create_reg (feature, "lr", 67, 1, NULL, 64, "code_ptr"); + tdesc_create_reg (feature, "ctr", 68, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "xer", 69, 1, NULL, 32, "uint32"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.fpu"); + tdesc_create_reg (feature, "f0", 32, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f1", 33, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f2", 34, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f3", 35, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f4", 36, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f5", 37, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f6", 38, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f7", 39, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f8", 40, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f9", 41, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f10", 42, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f11", 43, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f12", 44, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f13", 45, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f14", 46, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f15", 47, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f16", 48, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f17", 49, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f18", 50, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f19", 51, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f20", 52, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f21", 53, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f22", 54, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f23", 55, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f24", 56, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f25", 57, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f26", 58, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f27", 59, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f28", 60, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f29", 61, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f30", 62, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "f31", 63, 1, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "fpscr", 70, 1, "float", 64, "int"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.linux"); + tdesc_create_reg (feature, "orig_r3", 71, 1, NULL, 64, "int"); + tdesc_create_reg (feature, "trap", 72, 1, NULL, 64, "int"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.altivec"); + tdesc_type *element_type; + element_type = tdesc_named_type (feature, "ieee_single"); + tdesc_create_vector (feature, "v4f", element_type, 4); + + element_type = tdesc_named_type (feature, "int32"); + tdesc_create_vector (feature, "v4i32", element_type, 4); + + element_type = tdesc_named_type (feature, "int16"); + tdesc_create_vector (feature, "v8i16", element_type, 8); + + element_type = tdesc_named_type (feature, "int8"); + tdesc_create_vector (feature, "v16i8", element_type, 16); + + tdesc_type_with_fields *type_with_fields; + type_with_fields = tdesc_create_union (feature, "vec128"); + tdesc_type *field_type; + field_type = tdesc_named_type (feature, "uint128"); + tdesc_add_field (type_with_fields, "uint128", field_type); + field_type = tdesc_named_type (feature, "v4f"); + tdesc_add_field (type_with_fields, "v4_float", field_type); + field_type = tdesc_named_type (feature, "v4i32"); + tdesc_add_field (type_with_fields, "v4_int32", field_type); + field_type = tdesc_named_type (feature, "v8i16"); + tdesc_add_field (type_with_fields, "v8_int16", field_type); + field_type = tdesc_named_type (feature, "v16i8"); + tdesc_add_field (type_with_fields, "v16_int8", field_type); + + tdesc_create_reg (feature, "vr0", 73, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr1", 74, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr2", 75, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr3", 76, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr4", 77, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr5", 78, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr6", 79, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr7", 80, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr8", 81, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr9", 82, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr10", 83, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr11", 84, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr12", 85, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr13", 86, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr14", 87, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr15", 88, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr16", 89, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr17", 90, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr18", 91, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr19", 92, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr20", 93, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr21", 94, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr22", 95, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr23", 96, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr24", 97, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr25", 98, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr26", 99, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr27", 100, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr28", 101, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr29", 102, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr30", 103, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vr31", 104, 1, NULL, 128, "vec128"); + tdesc_create_reg (feature, "vscr", 105, 1, "vector", 32, "int"); + tdesc_create_reg (feature, "vrsave", 106, 1, "vector", 32, "int"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.vsx"); + tdesc_create_reg (feature, "vs0h", 107, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs1h", 108, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs2h", 109, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs3h", 110, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs4h", 111, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs5h", 112, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs6h", 113, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs7h", 114, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs8h", 115, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs9h", 116, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs10h", 117, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs11h", 118, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs12h", 119, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs13h", 120, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs14h", 121, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs15h", 122, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs16h", 123, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs17h", 124, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs18h", 125, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs19h", 126, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs20h", 127, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs21h", 128, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs22h", 129, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs23h", 130, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs24h", 131, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs25h", 132, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs26h", 133, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs27h", 134, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs28h", 135, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs29h", 136, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs30h", 137, 1, NULL, 64, "uint64"); + tdesc_create_reg (feature, "vs31h", 138, 1, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.ppr"); + tdesc_create_reg (feature, "ppr", 139, 1, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.dscr"); + tdesc_create_reg (feature, "dscr", 140, 1, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.tar"); + tdesc_create_reg (feature, "tar", 141, 1, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.ebb"); + tdesc_create_reg (feature, "bescr", 142, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "ebbhr", 143, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "ebbrr", 144, 0, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.linux.pmu"); + tdesc_create_reg (feature, "mmcr0", 145, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "mmcr2", 146, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "siar", 147, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "sdar", 148, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "sier", 149, 0, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.spr"); + tdesc_create_reg (feature, "tfhar", 150, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "texasr", 151, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "tfiar", 152, 0, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.core"); + tdesc_create_reg (feature, "cr0", 153, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr1", 154, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr2", 155, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr3", 156, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr4", 157, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr5", 158, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr6", 159, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr7", 160, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr8", 161, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr9", 162, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr10", 163, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr11", 164, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr12", 165, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr13", 166, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr14", 167, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr15", 168, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr16", 169, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr17", 170, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr18", 171, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr19", 172, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr20", 173, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr21", 174, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr22", 175, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr23", 176, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr24", 177, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr25", 178, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr26", 179, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr27", 180, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr28", 181, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr29", 182, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr30", 183, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cr31", 184, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "ccr", 185, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "cxer", 186, 0, NULL, 32, "uint32"); + tdesc_create_reg (feature, "clr", 187, 0, NULL, 64, "code_ptr"); + tdesc_create_reg (feature, "cctr", 188, 0, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.fpu"); + tdesc_create_reg (feature, "cf0", 189, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf1", 190, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf2", 191, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf3", 192, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf4", 193, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf5", 194, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf6", 195, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf7", 196, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf8", 197, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf9", 198, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf10", 199, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf11", 200, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf12", 201, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf13", 202, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf14", 203, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf15", 204, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf16", 205, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf17", 206, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf18", 207, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf19", 208, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf20", 209, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf21", 210, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf22", 211, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf23", 212, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf24", 213, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf25", 214, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf26", 215, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf27", 216, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf28", 217, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf29", 218, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf30", 219, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cf31", 220, 0, NULL, 64, "ieee_double"); + tdesc_create_reg (feature, "cfpscr", 221, 0, "float", 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.altivec"); + element_type = tdesc_named_type (feature, "ieee_single"); + tdesc_create_vector (feature, "v4f", element_type, 4); + + element_type = tdesc_named_type (feature, "int32"); + tdesc_create_vector (feature, "v4i32", element_type, 4); + + element_type = tdesc_named_type (feature, "int16"); + tdesc_create_vector (feature, "v8i16", element_type, 8); + + element_type = tdesc_named_type (feature, "int8"); + tdesc_create_vector (feature, "v16i8", element_type, 16); + + type_with_fields = tdesc_create_union (feature, "vec128"); + field_type = tdesc_named_type (feature, "uint128"); + tdesc_add_field (type_with_fields, "uint128", field_type); + field_type = tdesc_named_type (feature, "v4f"); + tdesc_add_field (type_with_fields, "v4_float", field_type); + field_type = tdesc_named_type (feature, "v4i32"); + tdesc_add_field (type_with_fields, "v4_int32", field_type); + field_type = tdesc_named_type (feature, "v8i16"); + tdesc_add_field (type_with_fields, "v8_int16", field_type); + field_type = tdesc_named_type (feature, "v16i8"); + tdesc_add_field (type_with_fields, "v16_int8", field_type); + + tdesc_create_reg (feature, "cvr0", 222, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr1", 223, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr2", 224, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr3", 225, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr4", 226, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr5", 227, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr6", 228, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr7", 229, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr8", 230, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr9", 231, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr10", 232, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr11", 233, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr12", 234, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr13", 235, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr14", 236, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr15", 237, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr16", 238, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr17", 239, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr18", 240, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr19", 241, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr20", 242, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr21", 243, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr22", 244, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr23", 245, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr24", 246, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr25", 247, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr26", 248, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr27", 249, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr28", 250, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr29", 251, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr30", 252, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvr31", 253, 0, NULL, 128, "vec128"); + tdesc_create_reg (feature, "cvscr", 254, 0, "vector", 32, "int"); + tdesc_create_reg (feature, "cvrsave", 255, 0, "vector", 32, "int"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.vsx"); + tdesc_create_reg (feature, "cvs0h", 256, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs1h", 257, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs2h", 258, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs3h", 259, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs4h", 260, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs5h", 261, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs6h", 262, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs7h", 263, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs8h", 264, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs9h", 265, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs10h", 266, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs11h", 267, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs12h", 268, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs13h", 269, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs14h", 270, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs15h", 271, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs16h", 272, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs17h", 273, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs18h", 274, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs19h", 275, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs20h", 276, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs21h", 277, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs22h", 278, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs23h", 279, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs24h", 280, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs25h", 281, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs26h", 282, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs27h", 283, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs28h", 284, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs29h", 285, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs30h", 286, 0, NULL, 64, "uint64"); + tdesc_create_reg (feature, "cvs31h", 287, 0, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.ppr"); + tdesc_create_reg (feature, "cppr", 288, 0, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.dscr"); + tdesc_create_reg (feature, "cdscr", 289, 0, NULL, 64, "uint64"); + + feature = tdesc_create_feature (result, "org.gnu.gdb.power.htm.tar"); + tdesc_create_reg (feature, "ctar", 290, 0, NULL, 64, "uint64"); + + tdesc_powerpc_isa207_htm_vsx64l = result; +} diff --git a/gdb/features/rs6000/powerpc-isa207-htm-vsx64l.xml b/gdb/features/rs6000/powerpc-isa207-htm-vsx64l.xml new file mode 100644 index 00000000000..28a8ea279b2 --- /dev/null +++ b/gdb/features/rs6000/powerpc-isa207-htm-vsx64l.xml @@ -0,0 +1,29 @@ + + + + + + powerpc:common64 + + + + + + + + + + + + + + + + + + + diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 56e724d0627..f7ae3515abc 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,38 @@ +2018-10-26 Pedro Franco de Carvalho + + * configure.srv (ipa_ppc_linux_regobj): Add + powerpc-isa207-htm-vsx32l-ipa.o and + powerpc-isa207-htm-vsx64l-ipa.o. + (powerpc*-*-linux*): Add powerpc-isa207-htm-vsx32l.o and + powerpc-isa207-htm-vsx64l.o to srv_regobj. Add + rs6000/power-htm-spr.xml, rs6000/power-htm-core.xml, + rs6000/power64-htm-core.xml, rs6000/power-htm-fpu.xml, + rs6000/power-htm-altivec.xml, rs6000/power-htm-vsx.xml, + rs6000/power-htm-ppr.xml, rs6000/power-htm-dscr.xml, + rs6000/power-htm-tar.xml, rs6000/powerpc-isa207-htm-vsx32l.xml, + and rs6000/powerpc-isa207-htm-vsx64l.xml to srv_xmlfiles. + * linux-ppc-tdesc-init.h (enum ppc_linux_tdesc) + : New enum value. + (init_registers_powerpc_isa207_htm_vsx32l) + (init_registers_powerpc_isa207_htm_vsx64l): Declare. + * linux-ppc-low.c (ppc_fill_tm_sprregset, ppc_store_tm_sprregset) + (ppc_store_tm_cgprregset, ppc_store_tm_cfprregset) + (ppc_store_tm_cvrregset, ppc_store_tm_cvsxregset) + (ppc_store_tm_cpprregset, ppc_store_tm_cdscrregset) + (ppc_store_tm_ctarregset): New functions. + (ppc_regsets): Add entries for HTM regsets. + (ppc_arch_setup): Set htm in features struct when needed. Set + sizes for the HTM regsets. + (ppc_get_ipa_tdesc_idx): Return PPC_TDESC_ISA207_HTM_VSX. + (initialize_low_arch): Call + init_registers_powerpc_isa207_htm_vsx32l and + init_registers_powerpc_isa207_htm_vsx64l. + * linux-ppc-ipa.c (get_ipa_tdesc): Handle + PPC_TDESC_ISA207_HTM_VSX. + (initialize_low_tracepoint): Call + init_registers_powerpc_isa207_htm_vsx32l and + init_registers_powerpc_isa207_htm_vsx64l. + 2018-10-26 Pedro Franco de Carvalho * configure.srv (powerpc*-*-linux*): Add rs6000/power-ebb.xml and diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv index eb5f2085f5e..d19d22b3a32 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -32,7 +32,7 @@ else srv_amd64_linux_regobj="" fi -ipa_ppc_linux_regobj="powerpc-32l-ipa.o powerpc-altivec32l-ipa.o powerpc-cell32l-ipa.o powerpc-vsx32l-ipa.o powerpc-isa205-32l-ipa.o powerpc-isa205-altivec32l-ipa.o powerpc-isa205-vsx32l-ipa.o powerpc-isa205-ppr-dscr-vsx32l-ipa.o powerpc-isa207-vsx32l-ipa.o powerpc-e500l-ipa.o powerpc-64l-ipa.o powerpc-altivec64l-ipa.o powerpc-cell64l-ipa.o powerpc-vsx64l-ipa.o powerpc-isa205-64l-ipa.o powerpc-isa205-altivec64l-ipa.o powerpc-isa205-vsx64l-ipa.o powerpc-isa205-ppr-dscr-vsx64l-ipa.o powerpc-isa207-vsx64l-ipa.o" +ipa_ppc_linux_regobj="powerpc-32l-ipa.o powerpc-altivec32l-ipa.o powerpc-cell32l-ipa.o powerpc-vsx32l-ipa.o powerpc-isa205-32l-ipa.o powerpc-isa205-altivec32l-ipa.o powerpc-isa205-vsx32l-ipa.o powerpc-isa205-ppr-dscr-vsx32l-ipa.o powerpc-isa207-vsx32l-ipa.o powerpc-isa207-htm-vsx32l-ipa.o powerpc-e500l-ipa.o powerpc-64l-ipa.o powerpc-altivec64l-ipa.o powerpc-cell64l-ipa.o powerpc-vsx64l-ipa.o powerpc-isa205-64l-ipa.o powerpc-isa205-altivec64l-ipa.o powerpc-isa205-vsx64l-ipa.o powerpc-isa205-ppr-dscr-vsx64l-ipa.o powerpc-isa207-vsx64l-ipa.o powerpc-isa207-htm-vsx64l-ipa.o" # Linux object files. This is so we don't have to repeat # these files over and over again. @@ -219,6 +219,7 @@ case "${target}" in srv_regobj="${srv_regobj} powerpc-isa205-vsx32l.o" srv_regobj="${srv_regobj} powerpc-isa205-ppr-dscr-vsx32l.o" srv_regobj="${srv_regobj} powerpc-isa207-vsx32l.o" + srv_regobj="${srv_regobj} powerpc-isa207-htm-vsx32l.o" srv_regobj="${srv_regobj} powerpc-e500l.o" srv_regobj="${srv_regobj} powerpc-64l.o" srv_regobj="${srv_regobj} powerpc-altivec64l.o" @@ -229,6 +230,7 @@ case "${target}" in srv_regobj="${srv_regobj} powerpc-isa205-vsx64l.o" srv_regobj="${srv_regobj} powerpc-isa205-ppr-dscr-vsx64l.o" srv_regobj="${srv_regobj} powerpc-isa207-vsx64l.o" + srv_regobj="${srv_regobj} powerpc-isa207-htm-vsx64l.o" srv_tgtobj="$srv_linux_obj linux-ppc-low.o ppc-linux.o" srv_tgtobj="${srv_tgtobj} arch/ppc-linux-common.o" srv_xmlfiles="rs6000/powerpc-32l.xml" @@ -240,6 +242,7 @@ case "${target}" in srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa205-vsx32l.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa205-ppr-dscr-vsx32l.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa207-vsx32l.xml" + srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa207-htm-vsx32l.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/power-altivec.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/power-vsx.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/power-core.xml" @@ -251,6 +254,14 @@ case "${target}" in srv_xmlfiles="${srv_xmlfiles} rs6000/power-tar.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/power-ebb.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/power-linux-pmu.xml" + srv_xmlfiles="${srv_xmlfiles} rs6000/power-htm-spr.xml" + srv_xmlfiles="${srv_xmlfiles} rs6000/power-htm-core.xml" + srv_xmlfiles="${srv_xmlfiles} rs6000/power-htm-fpu.xml" + srv_xmlfiles="${srv_xmlfiles} rs6000/power-htm-altivec.xml" + srv_xmlfiles="${srv_xmlfiles} rs6000/power-htm-vsx.xml" + srv_xmlfiles="${srv_xmlfiles} rs6000/power-htm-ppr.xml" + srv_xmlfiles="${srv_xmlfiles} rs6000/power-htm-dscr.xml" + srv_xmlfiles="${srv_xmlfiles} rs6000/power-htm-tar.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-e500l.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/power-spe.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-64l.xml" @@ -262,8 +273,10 @@ case "${target}" in srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa205-vsx64l.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa205-ppr-dscr-vsx64l.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa207-vsx64l.xml" + srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa207-htm-vsx64l.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/power64-core.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/power64-linux.xml" + srv_xmlfiles="${srv_xmlfiles} rs6000/power64-htm-core.xml" srv_linux_usrregs=yes srv_linux_regsets=yes srv_linux_thread_db=yes diff --git a/gdb/gdbserver/linux-ppc-ipa.c b/gdb/gdbserver/linux-ppc-ipa.c index b543dceba58..348d4551939 100644 --- a/gdb/gdbserver/linux-ppc-ipa.c +++ b/gdb/gdbserver/linux-ppc-ipa.c @@ -195,6 +195,8 @@ get_ipa_tdesc (int idx) return tdesc_powerpc_isa205_ppr_dscr_vsx64l; case PPC_TDESC_ISA207_VSX: return tdesc_powerpc_isa207_vsx64l; + case PPC_TDESC_ISA207_HTM_VSX: + return tdesc_powerpc_isa207_htm_vsx64l; #else case PPC_TDESC_BASE: return tdesc_powerpc_32l; @@ -214,6 +216,8 @@ get_ipa_tdesc (int idx) return tdesc_powerpc_isa205_ppr_dscr_vsx32l; case PPC_TDESC_ISA207_VSX: return tdesc_powerpc_isa207_vsx32l; + case PPC_TDESC_ISA207_HTM_VSX: + return tdesc_powerpc_isa207_htm_vsx32l; case PPC_TDESC_E500: return tdesc_powerpc_e500l; #endif @@ -244,6 +248,7 @@ initialize_low_tracepoint (void) init_registers_powerpc_isa205_vsx64l (); init_registers_powerpc_isa205_ppr_dscr_vsx64l (); init_registers_powerpc_isa207_vsx64l (); + init_registers_powerpc_isa207_htm_vsx64l (); #else init_registers_powerpc_32l (); init_registers_powerpc_altivec32l (); @@ -254,6 +259,7 @@ initialize_low_tracepoint (void) init_registers_powerpc_isa205_vsx32l (); init_registers_powerpc_isa205_ppr_dscr_vsx32l (); init_registers_powerpc_isa207_vsx32l (); + init_registers_powerpc_isa207_htm_vsx32l (); init_registers_powerpc_e500l (); #endif } diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c index e32815169d8..12cb56a2b20 100644 --- a/gdb/gdbserver/linux-ppc-low.c +++ b/gdb/gdbserver/linux-ppc-low.c @@ -600,6 +600,158 @@ ppc_store_pmuregset (struct regcache *regcache, const void *buf) supply_register_by_name (regcache, "mmcr0", ®set[32]); } +/* Hardware Transactional Memory special-purpose register regset fill + function. */ + +static void +ppc_fill_tm_sprregset (struct regcache *regcache, void *buf) +{ + int i, base; + char *regset = (char *) buf; + + base = find_regno (regcache->tdesc, "tfhar"); + for (i = 0; i < 3; i++) + collect_register (regcache, base + i, ®set[i * 8]); +} + +/* Hardware Transactional Memory special-purpose register regset store + function. */ + +static void +ppc_store_tm_sprregset (struct regcache *regcache, const void *buf) +{ + int i, base; + const char *regset = (const char *) buf; + + base = find_regno (regcache->tdesc, "tfhar"); + for (i = 0; i < 3; i++) + supply_register (regcache, base + i, ®set[i * 8]); +} + +/* For the same reasons as the EBB regset, none of the HTM + checkpointed regsets have a fill function. These registers are + only available if the inferior is in a transaction. */ + +/* Hardware Transactional Memory checkpointed general-purpose regset + store function. */ + +static void +ppc_store_tm_cgprregset (struct regcache *regcache, const void *buf) +{ + int i, base, size, endian_offset; + const char *regset = (const char *) buf; + + base = find_regno (regcache->tdesc, "cr0"); + size = register_size (regcache->tdesc, base); + + gdb_assert (size == 4 || size == 8); + + for (i = 0; i < 32; i++) + supply_register (regcache, base + i, ®set[i * size]); + + endian_offset = 0; + + if ((size == 8) && (__BYTE_ORDER == __BIG_ENDIAN)) + endian_offset = 4; + + supply_register_by_name (regcache, "ccr", + ®set[PT_CCR * size + endian_offset]); + + supply_register_by_name (regcache, "cxer", + ®set[PT_XER * size + endian_offset]); + + supply_register_by_name (regcache, "clr", ®set[PT_LNK * size]); + supply_register_by_name (regcache, "cctr", ®set[PT_CTR * size]); +} + +/* Hardware Transactional Memory checkpointed floating-point regset + store function. */ + +static void +ppc_store_tm_cfprregset (struct regcache *regcache, const void *buf) +{ + int i, base; + const char *regset = (const char *) buf; + + base = find_regno (regcache->tdesc, "cf0"); + + for (i = 0; i < 32; i++) + supply_register (regcache, base + i, ®set[i * 8]); + + supply_register_by_name (regcache, "cfpscr", ®set[32 * 8]); +} + +/* Hardware Transactional Memory checkpointed vector regset store + function. */ + +static void +ppc_store_tm_cvrregset (struct regcache *regcache, const void *buf) +{ + int i, base; + const char *regset = (const char *) buf; + int vscr_offset = 0; + + base = find_regno (regcache->tdesc, "cvr0"); + + for (i = 0; i < 32; i++) + supply_register (regcache, base + i, ®set[i * 16]); + + if (__BYTE_ORDER == __BIG_ENDIAN) + vscr_offset = 12; + + supply_register_by_name (regcache, "cvscr", + ®set[32 * 16 + vscr_offset]); + + supply_register_by_name (regcache, "cvrsave", ®set[33 * 16]); +} + +/* Hardware Transactional Memory checkpointed vector-scalar regset + store function. */ + +static void +ppc_store_tm_cvsxregset (struct regcache *regcache, const void *buf) +{ + int i, base; + const char *regset = (const char *) buf; + + base = find_regno (regcache->tdesc, "cvs0h"); + for (i = 0; i < 32; i++) + supply_register (regcache, base + i, ®set[i * 8]); +} + +/* Hardware Transactional Memory checkpointed Program Priority + Register regset store function. */ + +static void +ppc_store_tm_cpprregset (struct regcache *regcache, const void *buf) +{ + const char *cppr = (const char *) buf; + + supply_register_by_name (regcache, "cppr", cppr); +} + +/* Hardware Transactional Memory checkpointed Data Stream Control + Register regset store function. */ + +static void +ppc_store_tm_cdscrregset (struct regcache *regcache, const void *buf) +{ + const char *cdscr = (const char *) buf; + + supply_register_by_name (regcache, "cdscr", cdscr); +} + +/* Hardware Transactional Memory checkpointed Target Address Register + regset store function. */ + +static void +ppc_store_tm_ctarregset (struct regcache *regcache, const void *buf) +{ + const char *ctar = (const char *) buf; + + supply_register_by_name (regcache, "ctar", ctar); +} + static void ppc_fill_vsxregset (struct regcache *regcache, void *buf) { @@ -709,6 +861,22 @@ static struct regset_info ppc_regsets[] = { fetch them every time, but still fall back to PTRACE_PEEKUSER for the general registers. Some kernels support these, but not the newer PPC_PTRACE_GETREGS. */ + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_TM_CTAR, 0, EXTENDED_REGS, + NULL, ppc_store_tm_ctarregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_TM_CDSCR, 0, EXTENDED_REGS, + NULL, ppc_store_tm_cdscrregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_TM_CPPR, 0, EXTENDED_REGS, + NULL, ppc_store_tm_cpprregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_TM_CVSX, 0, EXTENDED_REGS, + NULL, ppc_store_tm_cvsxregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_TM_CVMX, 0, EXTENDED_REGS, + NULL, ppc_store_tm_cvrregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_TM_CFPR, 0, EXTENDED_REGS, + NULL, ppc_store_tm_cfprregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_TM_CGPR, 0, EXTENDED_REGS, + NULL, ppc_store_tm_cgprregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_TM_SPR, 0, EXTENDED_REGS, + ppc_fill_tm_sprregset, ppc_store_tm_sprregset }, { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_EBB, 0, EXTENDED_REGS, NULL, ppc_store_ebbregset }, { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_PMU, 0, EXTENDED_REGS, @@ -800,7 +968,13 @@ ppc_arch_setup (void) PPC_LINUX_SIZEOF_EBBREGSET) && ppc_check_regset (tid, NT_PPC_PMU, PPC_LINUX_SIZEOF_PMUREGSET)) - features.isa207 = true; + { + features.isa207 = true; + if ((ppc_hwcap2 & PPC_FEATURE2_HTM) + && ppc_check_regset (tid, NT_PPC_TM_SPR, + PPC_LINUX_SIZEOF_TM_SPRREGSET)) + features.htm = true; + } } if (ppc_hwcap & PPC_FEATURE_CELL) @@ -870,6 +1044,42 @@ ppc_arch_setup (void) regset->size = (features.isa207 ? PPC_LINUX_SIZEOF_PMUREGSET : 0); break; + case NT_PPC_TM_SPR: + regset->size = (features.htm ? + PPC_LINUX_SIZEOF_TM_SPRREGSET : 0); + break; + case NT_PPC_TM_CGPR: + if (features.wordsize == 4) + regset->size = (features.htm ? + PPC32_LINUX_SIZEOF_CGPRREGSET : 0); + else + regset->size = (features.htm ? + PPC64_LINUX_SIZEOF_CGPRREGSET : 0); + break; + case NT_PPC_TM_CFPR: + regset->size = (features.htm ? + PPC_LINUX_SIZEOF_CFPRREGSET : 0); + break; + case NT_PPC_TM_CVMX: + regset->size = (features.htm ? + PPC_LINUX_SIZEOF_CVMXREGSET : 0); + break; + case NT_PPC_TM_CVSX: + regset->size = (features.htm ? + PPC_LINUX_SIZEOF_CVSXREGSET : 0); + break; + case NT_PPC_TM_CPPR: + regset->size = (features.htm ? + PPC_LINUX_SIZEOF_CPPRREGSET : 0); + break; + case NT_PPC_TM_CDSCR: + regset->size = (features.htm ? + PPC_LINUX_SIZEOF_CDSCRREGSET : 0); + break; + case NT_PPC_TM_CTAR: + regset->size = (features.htm ? + PPC_LINUX_SIZEOF_CTARREGSET : 0); + break; default: break; } @@ -3253,6 +3463,8 @@ ppc_get_ipa_tdesc_idx (void) return PPC_TDESC_ISA205_PPR_DSCR_VSX; if (tdesc == tdesc_powerpc_isa207_vsx64l) return PPC_TDESC_ISA207_VSX; + if (tdesc == tdesc_powerpc_isa207_htm_vsx64l) + return PPC_TDESC_ISA207_HTM_VSX; #endif if (tdesc == tdesc_powerpc_32l) @@ -3273,6 +3485,8 @@ ppc_get_ipa_tdesc_idx (void) return PPC_TDESC_ISA205_PPR_DSCR_VSX; if (tdesc == tdesc_powerpc_isa207_vsx32l) return PPC_TDESC_ISA207_VSX; + if (tdesc == tdesc_powerpc_isa207_htm_vsx32l) + return PPC_TDESC_ISA207_HTM_VSX; if (tdesc == tdesc_powerpc_e500l) return PPC_TDESC_E500; @@ -3333,6 +3547,7 @@ initialize_low_arch (void) init_registers_powerpc_isa205_vsx32l (); init_registers_powerpc_isa205_ppr_dscr_vsx32l (); init_registers_powerpc_isa207_vsx32l (); + init_registers_powerpc_isa207_htm_vsx32l (); init_registers_powerpc_e500l (); #if __powerpc64__ init_registers_powerpc_64l (); @@ -3344,6 +3559,7 @@ initialize_low_arch (void) init_registers_powerpc_isa205_vsx64l (); init_registers_powerpc_isa205_ppr_dscr_vsx64l (); init_registers_powerpc_isa207_vsx64l (); + init_registers_powerpc_isa207_htm_vsx64l (); #endif initialize_regsets_info (&ppc_regsets_info); diff --git a/gdb/gdbserver/linux-ppc-tdesc-init.h b/gdb/gdbserver/linux-ppc-tdesc-init.h index 29b81228869..d1dfdad571d 100644 --- a/gdb/gdbserver/linux-ppc-tdesc-init.h +++ b/gdb/gdbserver/linux-ppc-tdesc-init.h @@ -31,6 +31,7 @@ enum ppc_linux_tdesc { PPC_TDESC_ISA205_VSX, PPC_TDESC_ISA205_PPR_DSCR_VSX, PPC_TDESC_ISA207_VSX, + PPC_TDESC_ISA207_HTM_VSX, PPC_TDESC_E500, }; @@ -63,6 +64,9 @@ void init_registers_powerpc_isa205_ppr_dscr_vsx32l (void); /* Defined in auto-generated file powerpc-isa207-vsx32l.c. */ void init_registers_powerpc_isa207_vsx32l (void); +/* Defined in auto-generated file powerpc-isa207-htm-vsx32l.c. */ +void init_registers_powerpc_isa207_htm_vsx32l (void); + /* Defined in auto-generated file powerpc-e500l.c. */ void init_registers_powerpc_e500l (void); @@ -97,4 +101,7 @@ void init_registers_powerpc_isa205_ppr_dscr_vsx64l (void); /* Defined in auto-generated file powerpc-isa207-vsx64l.c. */ void init_registers_powerpc_isa207_vsx64l (void); +/* Defined in auto-generated file powerpc-isa207-htm-vsx64l.c. */ +void init_registers_powerpc_isa207_htm_vsx64l (void); + #endif diff --git a/gdb/nat/ppc-linux.h b/gdb/nat/ppc-linux.h index c965030d91a..65c60cb158f 100644 --- a/gdb/nat/ppc-linux.h +++ b/gdb/nat/ppc-linux.h @@ -63,6 +63,9 @@ #ifndef PPC_FEATURE2_EBB #define PPC_FEATURE2_EBB 0x10000000 #endif +#ifndef PPC_FEATURE2_HTM +#define PPC_FEATURE2_HTM 0x40000000 +#endif /* Glibc's headers don't define PTRACE_GETVRREGS so we cannot use a configure time check. Some older glibc's (for instance 2.2.1) @@ -119,6 +122,46 @@ #define NT_PPC_PMU 0x107 #endif +/* TM checkpointed GPR Registers. */ +#ifndef NT_PPC_TM_CGPR +#define NT_PPC_TM_CGPR 0x108 +#endif + +/* TM checkpointed FPR Registers. */ +#ifndef NT_PPC_TM_CFPR +#define NT_PPC_TM_CFPR 0x109 +#endif + +/* TM checkpointed VMX Registers. */ +#ifndef NT_PPC_TM_CVMX +#define NT_PPC_TM_CVMX 0x10a +#endif + +/* TM checkpointed VSX Registers. */ +#ifndef NT_PPC_TM_CVSX +#define NT_PPC_TM_CVSX 0x10b +#endif + +/* TM Special Purpose Registers. */ +#ifndef NT_PPC_TM_SPR +#define NT_PPC_TM_SPR 0x10c +#endif + +/* TM checkpointed Target Address Register. */ +#ifndef NT_PPC_TM_CTAR +#define NT_PPC_TM_CTAR 0x10d +#endif + +/* TM checkpointed Program Priority Register. */ +#ifndef NT_PPC_TM_CPPR +#define NT_PPC_TM_CPPR 0x10e +#endif + +/* TM checkpointed Data Stream Control Register. */ +#ifndef NT_PPC_TM_CDSCR +#define NT_PPC_TM_CDSCR 0x10f +#endif + /* Return the wordsize of the target, either 4 or 8 bytes. */ int ppc_linux_target_wordsize (int tid); diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c index 0bbdcdc1efa..e83912de4bf 100644 --- a/gdb/ppc-linux-nat.c +++ b/gdb/ppc-linux-nat.c @@ -684,6 +684,82 @@ fetch_register (struct regcache *regcache, int tid, int regno) &ppc32_linux_pmuregset); return; } + else if (PPC_IS_TMSPR_REGNUM (regno)) + { + gdb_assert (tdep->have_htm_spr); + + fetch_regset (regcache, tid, NT_PPC_TM_SPR, + PPC_LINUX_SIZEOF_TM_SPRREGSET, + &ppc32_linux_tm_sprregset); + return; + } + else if (PPC_IS_CKPTGP_REGNUM (regno)) + { + gdb_assert (tdep->have_htm_core); + + const struct regset *cgprregset = ppc_linux_cgprregset (gdbarch); + fetch_regset (regcache, tid, NT_PPC_TM_CGPR, + (tdep->wordsize == 4? + PPC32_LINUX_SIZEOF_CGPRREGSET + : PPC64_LINUX_SIZEOF_CGPRREGSET), + cgprregset); + return; + } + else if (PPC_IS_CKPTFP_REGNUM (regno)) + { + gdb_assert (tdep->have_htm_fpu); + + fetch_regset (regcache, tid, NT_PPC_TM_CFPR, + PPC_LINUX_SIZEOF_CFPRREGSET, + &ppc32_linux_cfprregset); + return; + } + else if (PPC_IS_CKPTVMX_REGNUM (regno)) + { + gdb_assert (tdep->have_htm_altivec); + + const struct regset *cvmxregset = ppc_linux_cvmxregset (gdbarch); + fetch_regset (regcache, tid, NT_PPC_TM_CVMX, + PPC_LINUX_SIZEOF_CVMXREGSET, + cvmxregset); + return; + } + else if (PPC_IS_CKPTVSX_REGNUM (regno)) + { + gdb_assert (tdep->have_htm_vsx); + + fetch_regset (regcache, tid, NT_PPC_TM_CVSX, + PPC_LINUX_SIZEOF_CVSXREGSET, + &ppc32_linux_cvsxregset); + return; + } + else if (regno == PPC_CPPR_REGNUM) + { + gdb_assert (tdep->ppc_cppr_regnum != -1); + + fetch_regset (regcache, tid, NT_PPC_TM_CPPR, + PPC_LINUX_SIZEOF_CPPRREGSET, + &ppc32_linux_cpprregset); + return; + } + else if (regno == PPC_CDSCR_REGNUM) + { + gdb_assert (tdep->ppc_cdscr_regnum != -1); + + fetch_regset (regcache, tid, NT_PPC_TM_CDSCR, + PPC_LINUX_SIZEOF_CDSCRREGSET, + &ppc32_linux_cdscrregset); + return; + } + else if (regno == PPC_CTAR_REGNUM) + { + gdb_assert (tdep->ppc_ctar_regnum != -1); + + fetch_regset (regcache, tid, NT_PPC_TM_CTAR, + PPC_LINUX_SIZEOF_CTARREGSET, + &ppc32_linux_ctarregset); + return; + } if (regaddr == -1) { @@ -897,6 +973,46 @@ fetch_ppc_registers (struct regcache *regcache, int tid) fetch_regset (regcache, tid, NT_PPC_PMU, PPC_LINUX_SIZEOF_PMUREGSET, &ppc32_linux_pmuregset); + if (tdep->have_htm_spr) + fetch_regset (regcache, tid, NT_PPC_TM_SPR, + PPC_LINUX_SIZEOF_TM_SPRREGSET, + &ppc32_linux_tm_sprregset); + if (tdep->have_htm_core) + { + const struct regset *cgprregset = ppc_linux_cgprregset (gdbarch); + fetch_regset (regcache, tid, NT_PPC_TM_CGPR, + (tdep->wordsize == 4? + PPC32_LINUX_SIZEOF_CGPRREGSET + : PPC64_LINUX_SIZEOF_CGPRREGSET), + cgprregset); + } + if (tdep->have_htm_fpu) + fetch_regset (regcache, tid, NT_PPC_TM_CFPR, + PPC_LINUX_SIZEOF_CFPRREGSET, + &ppc32_linux_cfprregset); + if (tdep->have_htm_altivec) + { + const struct regset *cvmxregset = ppc_linux_cvmxregset (gdbarch); + fetch_regset (regcache, tid, NT_PPC_TM_CVMX, + PPC_LINUX_SIZEOF_CVMXREGSET, + cvmxregset); + } + if (tdep->have_htm_vsx) + fetch_regset (regcache, tid, NT_PPC_TM_CVSX, + PPC_LINUX_SIZEOF_CVSXREGSET, + &ppc32_linux_cvsxregset); + if (tdep->ppc_cppr_regnum != -1) + fetch_regset (regcache, tid, NT_PPC_TM_CPPR, + PPC_LINUX_SIZEOF_CPPRREGSET, + &ppc32_linux_cpprregset); + if (tdep->ppc_cdscr_regnum != -1) + fetch_regset (regcache, tid, NT_PPC_TM_CDSCR, + PPC_LINUX_SIZEOF_CDSCRREGSET, + &ppc32_linux_cdscrregset); + if (tdep->ppc_ctar_regnum != -1) + fetch_regset (regcache, tid, NT_PPC_TM_CTAR, + PPC_LINUX_SIZEOF_CTARREGSET, + &ppc32_linux_ctarregset); } /* Fetch registers from the child process. Fetch all registers if @@ -1122,6 +1238,82 @@ store_register (const struct regcache *regcache, int tid, int regno) &ppc32_linux_pmuregset); return; } + else if (PPC_IS_TMSPR_REGNUM (regno)) + { + gdb_assert (tdep->have_htm_spr); + + store_regset (regcache, tid, regno, NT_PPC_TM_SPR, + PPC_LINUX_SIZEOF_TM_SPRREGSET, + &ppc32_linux_tm_sprregset); + return; + } + else if (PPC_IS_CKPTGP_REGNUM (regno)) + { + gdb_assert (tdep->have_htm_core); + + const struct regset *cgprregset = ppc_linux_cgprregset (gdbarch); + store_regset (regcache, tid, regno, NT_PPC_TM_CGPR, + (tdep->wordsize == 4? + PPC32_LINUX_SIZEOF_CGPRREGSET + : PPC64_LINUX_SIZEOF_CGPRREGSET), + cgprregset); + return; + } + else if (PPC_IS_CKPTFP_REGNUM (regno)) + { + gdb_assert (tdep->have_htm_fpu); + + store_regset (regcache, tid, regno, NT_PPC_TM_CFPR, + PPC_LINUX_SIZEOF_CFPRREGSET, + &ppc32_linux_cfprregset); + return; + } + else if (PPC_IS_CKPTVMX_REGNUM (regno)) + { + gdb_assert (tdep->have_htm_altivec); + + const struct regset *cvmxregset = ppc_linux_cvmxregset (gdbarch); + store_regset (regcache, tid, regno, NT_PPC_TM_CVMX, + PPC_LINUX_SIZEOF_CVMXREGSET, + cvmxregset); + return; + } + else if (PPC_IS_CKPTVSX_REGNUM (regno)) + { + gdb_assert (tdep->have_htm_vsx); + + store_regset (regcache, tid, regno, NT_PPC_TM_CVSX, + PPC_LINUX_SIZEOF_CVSXREGSET, + &ppc32_linux_cvsxregset); + return; + } + else if (regno == PPC_CPPR_REGNUM) + { + gdb_assert (tdep->ppc_cppr_regnum != -1); + + store_regset (regcache, tid, regno, NT_PPC_TM_CPPR, + PPC_LINUX_SIZEOF_CPPRREGSET, + &ppc32_linux_cpprregset); + return; + } + else if (regno == PPC_CDSCR_REGNUM) + { + gdb_assert (tdep->ppc_cdscr_regnum != -1); + + store_regset (regcache, tid, regno, NT_PPC_TM_CDSCR, + PPC_LINUX_SIZEOF_CDSCRREGSET, + &ppc32_linux_cdscrregset); + return; + } + else if (regno == PPC_CTAR_REGNUM) + { + gdb_assert (tdep->ppc_ctar_regnum != -1); + + store_regset (regcache, tid, regno, NT_PPC_TM_CTAR, + PPC_LINUX_SIZEOF_CTARREGSET, + &ppc32_linux_ctarregset); + return; + } if (regaddr == -1) return; @@ -1351,9 +1543,14 @@ store_ppc_registers (const struct regcache *regcache, int tid) PPC_LINUX_SIZEOF_PMUREGSET, &ppc32_linux_pmuregset); - /* Because the EBB registers can be unavailable, attempts to store - them here would cause this function to fail most of the time, so - we ignore them. */ + if (tdep->have_htm_spr) + store_regset (regcache, tid, -1, NT_PPC_TM_SPR, + PPC_LINUX_SIZEOF_TM_SPRREGSET, + &ppc32_linux_tm_sprregset); + + /* Because the EBB and checkpointed HTM registers can be + unavailable, attempts to store them here would cause this + function to fail most of the time, so we ignore them. */ } /* Fetch the AT_HWCAP entry from the aux vector. */ @@ -2486,7 +2683,13 @@ ppc_linux_nat_target::read_description () && check_regset (tid, NT_PPC_TAR, PPC_LINUX_SIZEOF_TARREGSET) && check_regset (tid, NT_PPC_EBB, PPC_LINUX_SIZEOF_EBBREGSET) && check_regset (tid, NT_PPC_PMU, PPC_LINUX_SIZEOF_PMUREGSET)) - features.isa207 = true; + { + features.isa207 = true; + if ((hwcap2 & PPC_FEATURE2_HTM) + && check_regset (tid, NT_PPC_TM_SPR, + PPC_LINUX_SIZEOF_TM_SPRREGSET)) + features.htm = true; + } } return ppc_linux_match_description (features); diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 337ba67ed01..ed44cbe5552 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -73,6 +73,7 @@ #include "features/rs6000/powerpc-isa205-vsx32l.c" #include "features/rs6000/powerpc-isa205-ppr-dscr-vsx32l.c" #include "features/rs6000/powerpc-isa207-vsx32l.c" +#include "features/rs6000/powerpc-isa207-htm-vsx32l.c" #include "features/rs6000/powerpc-64l.c" #include "features/rs6000/powerpc-altivec64l.c" #include "features/rs6000/powerpc-cell64l.c" @@ -82,6 +83,7 @@ #include "features/rs6000/powerpc-isa205-vsx64l.c" #include "features/rs6000/powerpc-isa205-ppr-dscr-vsx64l.c" #include "features/rs6000/powerpc-isa207-vsx64l.c" +#include "features/rs6000/powerpc-isa207-htm-vsx64l.c" #include "features/rs6000/powerpc-e500l.c" /* Shared library operations for PowerPC-Linux. */ @@ -637,6 +639,239 @@ const struct regset ppc32_linux_pmuregset = { regcache_collect_regset }; +/* Hardware Transactional Memory special-purpose register regmap. */ + +static const struct regcache_map_entry ppc32_regmap_tm_spr[] = + { + { 1, PPC_TFHAR_REGNUM, 8 }, + { 1, PPC_TEXASR_REGNUM, 8 }, + { 1, PPC_TFIAR_REGNUM, 8 }, + { 0 } + }; + +/* Hardware Transactional Memory special-purpose register regset. */ + +const struct regset ppc32_linux_tm_sprregset = { + ppc32_regmap_tm_spr, + regcache_supply_regset, + regcache_collect_regset +}; + +/* Regmaps for the Hardware Transactional Memory checkpointed + general-purpose regsets for 32-bit, 64-bit big-endian, and 64-bit + little endian targets. The ptrace and core file buffers for 64-bit + targets use 8-byte fields for the 4-byte registers, and the + position of the register in the fields depends on the endianess. + The 32-bit regmap is the same for both endian types because the + fields are all 4-byte long. + + The layout of checkpointed GPR regset is the same as a regular + struct pt_regs, but we skip all registers that are not actually + checkpointed by the processor (e.g. msr, nip), except when + generating a core file. The 64-bit regset is 48 * 8 bytes long. + In some 64-bit kernels, the regset for a 32-bit inferior has the + same length, but all the registers are squeezed in the first half + (48 * 4 bytes). The pt_regs struct calls the regular cr ccr, but + we use ccr for "checkpointed condition register". Note that CR + (condition register) field 0 is not checkpointed, but the kernel + returns all 4 bytes. The skipped registers should not be touched + when writing the regset to the inferior (with + PTRACE_SETREGSET). */ + +static const struct regcache_map_entry ppc32_regmap_cgpr[] = + { + { 32, PPC_CR0_REGNUM, 4 }, + { 3, REGCACHE_MAP_SKIP, 4 }, /* nip, msr, orig_gpr3. */ + { 1, PPC_CCTR_REGNUM, 4 }, + { 1, PPC_CLR_REGNUM, 4 }, + { 1, PPC_CXER_REGNUM, 4 }, + { 1, PPC_CCR_REGNUM, 4 }, + { 9, REGCACHE_MAP_SKIP, 4 }, /* All the rest. */ + { 0 } + }; + +static const struct regcache_map_entry ppc64_le_regmap_cgpr[] = + { + { 32, PPC_CR0_REGNUM, 8 }, + { 3, REGCACHE_MAP_SKIP, 8 }, + { 1, PPC_CCTR_REGNUM, 8 }, + { 1, PPC_CLR_REGNUM, 8 }, + { 1, PPC_CXER_REGNUM, 4 }, + { 1, REGCACHE_MAP_SKIP, 4 }, /* CXER padding. */ + { 1, PPC_CCR_REGNUM, 4 }, + { 1, REGCACHE_MAP_SKIP, 4}, /* CCR padding. */ + { 9, REGCACHE_MAP_SKIP, 8}, + { 0 } + }; + +static const struct regcache_map_entry ppc64_be_regmap_cgpr[] = + { + { 32, PPC_CR0_REGNUM, 8 }, + { 3, REGCACHE_MAP_SKIP, 8 }, + { 1, PPC_CCTR_REGNUM, 8 }, + { 1, PPC_CLR_REGNUM, 8 }, + { 1, REGCACHE_MAP_SKIP, 4}, /* CXER padding. */ + { 1, PPC_CXER_REGNUM, 4 }, + { 1, REGCACHE_MAP_SKIP, 4}, /* CCR padding. */ + { 1, PPC_CCR_REGNUM, 4 }, + { 9, REGCACHE_MAP_SKIP, 8}, + { 0 } + }; + +/* Regsets for the Hardware Transactional Memory checkpointed + general-purpose registers for 32-bit, 64-bit big-endian, and 64-bit + little endian targets. + + Some 64-bit kernels generate a checkpointed gpr note section with + 48*8 bytes for a 32-bit thread, of which only 48*4 are actually + used, so we set the variable size flag in the corresponding regset + to accept this case. */ + +static const struct regset ppc32_linux_cgprregset = { + ppc32_regmap_cgpr, + regcache_supply_regset, + regcache_collect_regset, + REGSET_VARIABLE_SIZE +}; + +static const struct regset ppc64_be_linux_cgprregset = { + ppc64_be_regmap_cgpr, + regcache_supply_regset, + regcache_collect_regset +}; + +static const struct regset ppc64_le_linux_cgprregset = { + ppc64_le_regmap_cgpr, + regcache_supply_regset, + regcache_collect_regset +}; + +/* Hardware Transactional Memory checkpointed floating-point regmap. */ + +static const struct regcache_map_entry ppc32_regmap_cfpr[] = + { + { 32, PPC_CF0_REGNUM, 8 }, + { 1, PPC_CFPSCR_REGNUM, 8 }, + { 0 } + }; + +/* Hardware Transactional Memory checkpointed floating-point regset. */ + +const struct regset ppc32_linux_cfprregset = { + ppc32_regmap_cfpr, + regcache_supply_regset, + regcache_collect_regset +}; + +/* Regmaps for the Hardware Transactional Memory checkpointed vector + regsets, for big and little endian targets. The position of the + 4-byte VSCR in its 16-byte field depends on the endianess. */ + +static const struct regcache_map_entry ppc32_le_regmap_cvmx[] = + { + { 32, PPC_CVR0_REGNUM, 16 }, + { 1, PPC_CVSCR_REGNUM, 4 }, + { 1, REGCACHE_MAP_SKIP, 12 }, + { 1, PPC_CVRSAVE_REGNUM, 4 }, + { 1, REGCACHE_MAP_SKIP, 12 }, + { 0 } + }; + +static const struct regcache_map_entry ppc32_be_regmap_cvmx[] = + { + { 32, PPC_CVR0_REGNUM, 16 }, + { 1, REGCACHE_MAP_SKIP, 12 }, + { 1, PPC_CVSCR_REGNUM, 4 }, + { 1, PPC_CVRSAVE_REGNUM, 4 }, + { 1, REGCACHE_MAP_SKIP, 12}, + { 0 } + }; + +/* Hardware Transactional Memory checkpointed vector regsets, for little + and big endian targets. */ + +static const struct regset ppc32_le_linux_cvmxregset = { + ppc32_le_regmap_cvmx, + regcache_supply_regset, + regcache_collect_regset +}; + +static const struct regset ppc32_be_linux_cvmxregset = { + ppc32_be_regmap_cvmx, + regcache_supply_regset, + regcache_collect_regset +}; + +/* Hardware Transactional Memory checkpointed vector-scalar regmap. */ + +static const struct regcache_map_entry ppc32_regmap_cvsx[] = + { + { 32, PPC_CVSR0_UPPER_REGNUM, 8 }, + { 0 } + }; + +/* Hardware Transactional Memory checkpointed vector-scalar regset. */ + +const struct regset ppc32_linux_cvsxregset = { + ppc32_regmap_cvsx, + regcache_supply_regset, + regcache_collect_regset +}; + +/* Hardware Transactional Memory checkpointed Program Priority Register + regmap. */ + +static const struct regcache_map_entry ppc32_regmap_cppr[] = + { + { 1, PPC_CPPR_REGNUM, 8 }, + { 0 } + }; + +/* Hardware Transactional Memory checkpointed Program Priority Register + regset. */ + +const struct regset ppc32_linux_cpprregset = { + ppc32_regmap_cppr, + regcache_supply_regset, + regcache_collect_regset +}; + +/* Hardware Transactional Memory checkpointed Data Stream Control + Register regmap. */ + +static const struct regcache_map_entry ppc32_regmap_cdscr[] = + { + { 1, PPC_CDSCR_REGNUM, 8 }, + { 0 } + }; + +/* Hardware Transactional Memory checkpointed Data Stream Control + Register regset. */ + +const struct regset ppc32_linux_cdscrregset = { + ppc32_regmap_cdscr, + regcache_supply_regset, + regcache_collect_regset +}; + +/* Hardware Transactional Memory checkpointed Target Address Register + regmap. */ + +static const struct regcache_map_entry ppc32_regmap_ctar[] = + { + { 1, PPC_CTAR_REGNUM, 8 }, + { 0 } + }; + +/* Hardware Transactional Memory checkpointed Target Address Register + regset. */ + +const struct regset ppc32_linux_ctarregset = { + ppc32_regmap_ctar, + regcache_supply_regset, + regcache_collect_regset +}; + const struct regset * ppc_linux_gregset (int wordsize) { @@ -664,6 +899,88 @@ ppc_linux_vsxregset (void) return &ppc32_linux_vsxregset; } +const struct regset * +ppc_linux_cgprregset (struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (tdep->wordsize == 4) + { + return &ppc32_linux_cgprregset; + } + else + { + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + return &ppc64_be_linux_cgprregset; + else + return &ppc64_le_linux_cgprregset; + } +} + +const struct regset * +ppc_linux_cvmxregset (struct gdbarch *gdbarch) +{ + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + return &ppc32_be_linux_cvmxregset; + else + return &ppc32_le_linux_cvmxregset; +} + +/* Collect function used to generate the core note for the + checkpointed GPR regset. Here, we don't want to skip the + "checkpointed" NIP and MSR, so that the note section we generate is + similar to the one generated by the kernel. To avoid having to + define additional registers in GDB which are not actually + checkpointed in the architecture, we copy TFHAR to the checkpointed + NIP slot, which is what the kernel does, and copy the regular MSR + to the checkpointed MSR slot, which will have a similar value in + most cases. */ + +static void +ppc_linux_collect_core_cpgrregset (const struct regset *regset, + const struct regcache *regcache, + int regnum, void *buf, size_t len) +{ + struct gdbarch *gdbarch = regcache->arch (); + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + const struct regset *cgprregset = ppc_linux_cgprregset (gdbarch); + + /* We collect the checkpointed GPRs already defined in the regular + regmap, then overlay TFHAR/MSR on the checkpointed NIP/MSR + slots. */ + cgprregset->collect_regset (cgprregset, regcache, regnum, buf, len); + + /* Check that we are collecting all the registers, which should be + the case when generating a core file. */ + if (regnum != -1) + return; + + /* PT_NIP and PT_MSR are 32 and 33 for powerpc. Don't redefine + these symbols since this file can run on clients in other + architectures where they can already be defined to other + values. */ + int pt_offset = 32; + + /* Check that our buffer is long enough to hold two slots at + pt_offset * wordsize, one for NIP and one for MSR. */ + gdb_assert ((pt_offset + 2) * tdep->wordsize <= len); + + /* TFHAR is 8 bytes wide, but the NIP slot for a 32-bit thread is + 4-bytes long. We use raw_collect_integer which handles + differences in the sizes for the source and destination buffers + for both endian modes. */ + (regcache->raw_collect_integer + (PPC_TFHAR_REGNUM, ((gdb_byte *) buf) + pt_offset * tdep->wordsize, + tdep->wordsize, false)); + + pt_offset = 33; + + (regcache->raw_collect_integer + (PPC_MSR_REGNUM, ((gdb_byte *) buf) + pt_offset * tdep->wordsize, + tdep->wordsize, false)); +} + /* Iterate over supported core file register note sections. */ static void @@ -728,6 +1045,121 @@ ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, PPC_LINUX_SIZEOF_PMUREGSET, &ppc32_linux_pmuregset, "Performance Monitor Registers", cb_data); + + if (tdep->have_htm_spr) + cb (".reg-ppc-tm-spr", PPC_LINUX_SIZEOF_TM_SPRREGSET, + PPC_LINUX_SIZEOF_TM_SPRREGSET, + &ppc32_linux_tm_sprregset, + "Hardware Transactional Memory Special Purpose Registers", + cb_data); + + /* Checkpointed registers can be unavailable, don't call back if + we are generating a core file. */ + + if (tdep->have_htm_core) + { + /* Only generate the checkpointed GPR core note if we also have + access to the HTM SPRs, because we need TFHAR to fill the + "checkpointed" NIP slot. We can read a core file without it + since GDB is not aware of this NIP as a visible register. */ + if (regcache == NULL || + (REG_VALID == regcache->get_register_status (PPC_CR0_REGNUM) + && tdep->have_htm_spr)) + { + int cgpr_size = (tdep->wordsize == 4? + PPC32_LINUX_SIZEOF_CGPRREGSET + : PPC64_LINUX_SIZEOF_CGPRREGSET); + + const struct regset *cgprregset = + ppc_linux_cgprregset (gdbarch); + + if (regcache != NULL) + { + struct regset core_cgprregset = *cgprregset; + + core_cgprregset.collect_regset + = ppc_linux_collect_core_cpgrregset; + + cb (".reg-ppc-tm-cgpr", + cgpr_size, cgpr_size, + &core_cgprregset, + "Checkpointed General Purpose Registers", cb_data); + } + else + { + cb (".reg-ppc-tm-cgpr", + cgpr_size, cgpr_size, + cgprregset, + "Checkpointed General Purpose Registers", cb_data); + } + } + } + + if (tdep->have_htm_fpu) + { + if (regcache == NULL || + REG_VALID == regcache->get_register_status (PPC_CF0_REGNUM)) + cb (".reg-ppc-tm-cfpr", PPC_LINUX_SIZEOF_CFPRREGSET, + PPC_LINUX_SIZEOF_CFPRREGSET, + &ppc32_linux_cfprregset, + "Checkpointed Floating Point Registers", cb_data); + } + + if (tdep->have_htm_altivec) + { + if (regcache == NULL || + REG_VALID == regcache->get_register_status (PPC_CVR0_REGNUM)) + { + const struct regset *cvmxregset = + ppc_linux_cvmxregset (gdbarch); + + cb (".reg-ppc-tm-cvmx", PPC_LINUX_SIZEOF_CVMXREGSET, + PPC_LINUX_SIZEOF_CVMXREGSET, + cvmxregset, + "Checkpointed Altivec (VMX) Registers", cb_data); + } + } + + if (tdep->have_htm_vsx) + { + if (regcache == NULL || + (REG_VALID + == regcache->get_register_status (PPC_CVSR0_UPPER_REGNUM))) + cb (".reg-ppc-tm-cvsx", PPC_LINUX_SIZEOF_CVSXREGSET, + PPC_LINUX_SIZEOF_CVSXREGSET, + &ppc32_linux_cvsxregset, + "Checkpointed VSX Registers", cb_data); + } + + if (tdep->ppc_cppr_regnum != -1) + { + if (regcache == NULL || + REG_VALID == regcache->get_register_status (PPC_CPPR_REGNUM)) + cb (".reg-ppc-tm-cppr", PPC_LINUX_SIZEOF_CPPRREGSET, + PPC_LINUX_SIZEOF_CPPRREGSET, + &ppc32_linux_cpprregset, + "Checkpointed Priority Program Register", cb_data); + } + + if (tdep->ppc_cdscr_regnum != -1) + { + if (regcache == NULL || + REG_VALID == regcache->get_register_status (PPC_CDSCR_REGNUM)) + cb (".reg-ppc-tm-cdscr", PPC_LINUX_SIZEOF_CDSCRREGSET, + PPC_LINUX_SIZEOF_CDSCRREGSET, + &ppc32_linux_cdscrregset, + "Checkpointed Data Stream Control Register", cb_data); + } + + if (tdep->ppc_ctar_regnum) + { + if ( regcache == NULL || + REG_VALID == regcache->get_register_status (PPC_CTAR_REGNUM)) + cb (".reg-ppc-tm-ctar", PPC_LINUX_SIZEOF_CTARREGSET, + PPC_LINUX_SIZEOF_CTARREGSET, + &ppc32_linux_ctarregset, + "Checkpointed Target Address Register", cb_data); + } } static void @@ -1143,6 +1575,7 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch, asection *dscr = bfd_get_section_by_name (abfd, ".reg-ppc-dscr"); asection *tar = bfd_get_section_by_name (abfd, ".reg-ppc-tar"); asection *pmu = bfd_get_section_by_name (abfd, ".reg-ppc-pmu"); + asection *htmspr = bfd_get_section_by_name (abfd, ".reg-ppc-tm-spr"); if (! section) return NULL; @@ -1184,7 +1617,11 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch, been unavailable when the core file was created. They will be in the tdep but will show as unavailable. */ if (tar && pmu) - features.isa207 = true; + { + features.isa207 = true; + if (htmspr) + features.htm = true; + } } return ppc_linux_match_description (features); @@ -2062,6 +2499,7 @@ _initialize_ppc_linux_tdep (void) initialize_tdesc_powerpc_isa205_vsx32l (); initialize_tdesc_powerpc_isa205_ppr_dscr_vsx32l (); initialize_tdesc_powerpc_isa207_vsx32l (); + initialize_tdesc_powerpc_isa207_htm_vsx32l (); initialize_tdesc_powerpc_64l (); initialize_tdesc_powerpc_altivec64l (); initialize_tdesc_powerpc_cell64l (); @@ -2071,5 +2509,6 @@ _initialize_ppc_linux_tdep (void) initialize_tdesc_powerpc_isa205_vsx64l (); initialize_tdesc_powerpc_isa205_ppr_dscr_vsx64l (); initialize_tdesc_powerpc_isa207_vsx64l (); + initialize_tdesc_powerpc_isa207_htm_vsx64l (); initialize_tdesc_powerpc_e500l (); } diff --git a/gdb/ppc-linux-tdep.h b/gdb/ppc-linux-tdep.h index cce1ddd1efc..5fb42c9525e 100644 --- a/gdb/ppc-linux-tdep.h +++ b/gdb/ppc-linux-tdep.h @@ -32,6 +32,14 @@ const struct regset *ppc_linux_fpregset (void); const struct regset *ppc_linux_vrregset (struct gdbarch *gdbarch); const struct regset *ppc_linux_vsxregset (void); +/* Get the checkpointed GPR regset that matches the target wordsize + and byteorder of GDBARCH. */ +const struct regset *ppc_linux_cgprregset (struct gdbarch *gdbarch); + +/* Get the checkpointed vector regset that matches the target byte + order. */ +const struct regset* ppc_linux_cvmxregset (struct gdbarch *gdbarch); + /* Extra register number constants. The Linux kernel stores a "trap" code and the original value of r3 into special "registers"; these need to be saved and restored when performing an inferior @@ -50,5 +58,11 @@ extern const struct regset ppc32_linux_dscrregset; extern const struct regset ppc32_linux_tarregset; extern const struct regset ppc32_linux_ebbregset; extern const struct regset ppc32_linux_pmuregset; +extern const struct regset ppc32_linux_tm_sprregset; +extern const struct regset ppc32_linux_cfprregset; +extern const struct regset ppc32_linux_cvsxregset; +extern const struct regset ppc32_linux_cpprregset; +extern const struct regset ppc32_linux_cdscrregset; +extern const struct regset ppc32_linux_ctarregset; #endif /* PPC_LINUX_TDEP_H */ diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h index cfe32c9e874..dbafe2232d6 100644 --- a/gdb/ppc-tdep.h +++ b/gdb/ppc-tdep.h @@ -274,6 +274,21 @@ struct gdbarch_tdep 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; @@ -343,6 +358,29 @@ enum { 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 }; @@ -355,6 +393,21 @@ enum { #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 diff --git a/gdb/regformats/rs6000/powerpc-isa207-htm-vsx32l.dat b/gdb/regformats/rs6000/powerpc-isa207-htm-vsx32l.dat new file mode 100644 index 00000000000..c19416db868 --- /dev/null +++ b/gdb/regformats/rs6000/powerpc-isa207-htm-vsx32l.dat @@ -0,0 +1,296 @@ +# THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi :set ro: +# Generated from: rs6000/powerpc-isa207-htm-vsx32l.xml +name:powerpc_isa207_htm_vsx32l +xmltarget:powerpc-isa207-htm-vsx32l.xml +expedite:r1,pc +32:r0 +32:r1 +32:r2 +32:r3 +32:r4 +32:r5 +32:r6 +32:r7 +32:r8 +32:r9 +32:r10 +32:r11 +32:r12 +32:r13 +32:r14 +32:r15 +32:r16 +32:r17 +32:r18 +32:r19 +32:r20 +32:r21 +32:r22 +32:r23 +32:r24 +32:r25 +32:r26 +32:r27 +32:r28 +32:r29 +32:r30 +32:r31 +64:f0 +64:f1 +64:f2 +64:f3 +64:f4 +64:f5 +64:f6 +64:f7 +64:f8 +64:f9 +64:f10 +64:f11 +64:f12 +64:f13 +64:f14 +64:f15 +64:f16 +64:f17 +64:f18 +64:f19 +64:f20 +64:f21 +64:f22 +64:f23 +64:f24 +64:f25 +64:f26 +64:f27 +64:f28 +64:f29 +64:f30 +64:f31 +32:pc +32:msr +32:cr +32:lr +32:ctr +32:xer +64:fpscr +32:orig_r3 +32:trap +128:vr0 +128:vr1 +128:vr2 +128:vr3 +128:vr4 +128:vr5 +128:vr6 +128:vr7 +128:vr8 +128:vr9 +128:vr10 +128:vr11 +128:vr12 +128:vr13 +128:vr14 +128:vr15 +128:vr16 +128:vr17 +128:vr18 +128:vr19 +128:vr20 +128:vr21 +128:vr22 +128:vr23 +128:vr24 +128:vr25 +128:vr26 +128:vr27 +128:vr28 +128:vr29 +128:vr30 +128:vr31 +32:vscr +32:vrsave +64:vs0h +64:vs1h +64:vs2h +64:vs3h +64:vs4h +64:vs5h +64:vs6h +64:vs7h +64:vs8h +64:vs9h +64:vs10h +64:vs11h +64:vs12h +64:vs13h +64:vs14h +64:vs15h +64:vs16h +64:vs17h +64:vs18h +64:vs19h +64:vs20h +64:vs21h +64:vs22h +64:vs23h +64:vs24h +64:vs25h +64:vs26h +64:vs27h +64:vs28h +64:vs29h +64:vs30h +64:vs31h +64:ppr +64:dscr +64:tar +64:bescr +64:ebbhr +64:ebbrr +64:mmcr0 +64:mmcr2 +64:siar +64:sdar +64:sier +64:tfhar +64:texasr +64:tfiar +32:cr0 +32:cr1 +32:cr2 +32:cr3 +32:cr4 +32:cr5 +32:cr6 +32:cr7 +32:cr8 +32:cr9 +32:cr10 +32:cr11 +32:cr12 +32:cr13 +32:cr14 +32:cr15 +32:cr16 +32:cr17 +32:cr18 +32:cr19 +32:cr20 +32:cr21 +32:cr22 +32:cr23 +32:cr24 +32:cr25 +32:cr26 +32:cr27 +32:cr28 +32:cr29 +32:cr30 +32:cr31 +32:ccr +32:cxer +32:clr +32:cctr +64:cf0 +64:cf1 +64:cf2 +64:cf3 +64:cf4 +64:cf5 +64:cf6 +64:cf7 +64:cf8 +64:cf9 +64:cf10 +64:cf11 +64:cf12 +64:cf13 +64:cf14 +64:cf15 +64:cf16 +64:cf17 +64:cf18 +64:cf19 +64:cf20 +64:cf21 +64:cf22 +64:cf23 +64:cf24 +64:cf25 +64:cf26 +64:cf27 +64:cf28 +64:cf29 +64:cf30 +64:cf31 +64:cfpscr +128:cvr0 +128:cvr1 +128:cvr2 +128:cvr3 +128:cvr4 +128:cvr5 +128:cvr6 +128:cvr7 +128:cvr8 +128:cvr9 +128:cvr10 +128:cvr11 +128:cvr12 +128:cvr13 +128:cvr14 +128:cvr15 +128:cvr16 +128:cvr17 +128:cvr18 +128:cvr19 +128:cvr20 +128:cvr21 +128:cvr22 +128:cvr23 +128:cvr24 +128:cvr25 +128:cvr26 +128:cvr27 +128:cvr28 +128:cvr29 +128:cvr30 +128:cvr31 +32:cvscr +32:cvrsave +64:cvs0h +64:cvs1h +64:cvs2h +64:cvs3h +64:cvs4h +64:cvs5h +64:cvs6h +64:cvs7h +64:cvs8h +64:cvs9h +64:cvs10h +64:cvs11h +64:cvs12h +64:cvs13h +64:cvs14h +64:cvs15h +64:cvs16h +64:cvs17h +64:cvs18h +64:cvs19h +64:cvs20h +64:cvs21h +64:cvs22h +64:cvs23h +64:cvs24h +64:cvs25h +64:cvs26h +64:cvs27h +64:cvs28h +64:cvs29h +64:cvs30h +64:cvs31h +64:cppr +64:cdscr +64:ctar diff --git a/gdb/regformats/rs6000/powerpc-isa207-htm-vsx64l.dat b/gdb/regformats/rs6000/powerpc-isa207-htm-vsx64l.dat new file mode 100644 index 00000000000..38359959fd7 --- /dev/null +++ b/gdb/regformats/rs6000/powerpc-isa207-htm-vsx64l.dat @@ -0,0 +1,296 @@ +# THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi :set ro: +# Generated from: rs6000/powerpc-isa207-htm-vsx64l.xml +name:powerpc_isa207_htm_vsx64l +xmltarget:powerpc-isa207-htm-vsx64l.xml +expedite:r1,pc +64:r0 +64:r1 +64:r2 +64:r3 +64:r4 +64:r5 +64:r6 +64:r7 +64:r8 +64:r9 +64:r10 +64:r11 +64:r12 +64:r13 +64:r14 +64:r15 +64:r16 +64:r17 +64:r18 +64:r19 +64:r20 +64:r21 +64:r22 +64:r23 +64:r24 +64:r25 +64:r26 +64:r27 +64:r28 +64:r29 +64:r30 +64:r31 +64:f0 +64:f1 +64:f2 +64:f3 +64:f4 +64:f5 +64:f6 +64:f7 +64:f8 +64:f9 +64:f10 +64:f11 +64:f12 +64:f13 +64:f14 +64:f15 +64:f16 +64:f17 +64:f18 +64:f19 +64:f20 +64:f21 +64:f22 +64:f23 +64:f24 +64:f25 +64:f26 +64:f27 +64:f28 +64:f29 +64:f30 +64:f31 +64:pc +64:msr +32:cr +64:lr +64:ctr +32:xer +64:fpscr +64:orig_r3 +64:trap +128:vr0 +128:vr1 +128:vr2 +128:vr3 +128:vr4 +128:vr5 +128:vr6 +128:vr7 +128:vr8 +128:vr9 +128:vr10 +128:vr11 +128:vr12 +128:vr13 +128:vr14 +128:vr15 +128:vr16 +128:vr17 +128:vr18 +128:vr19 +128:vr20 +128:vr21 +128:vr22 +128:vr23 +128:vr24 +128:vr25 +128:vr26 +128:vr27 +128:vr28 +128:vr29 +128:vr30 +128:vr31 +32:vscr +32:vrsave +64:vs0h +64:vs1h +64:vs2h +64:vs3h +64:vs4h +64:vs5h +64:vs6h +64:vs7h +64:vs8h +64:vs9h +64:vs10h +64:vs11h +64:vs12h +64:vs13h +64:vs14h +64:vs15h +64:vs16h +64:vs17h +64:vs18h +64:vs19h +64:vs20h +64:vs21h +64:vs22h +64:vs23h +64:vs24h +64:vs25h +64:vs26h +64:vs27h +64:vs28h +64:vs29h +64:vs30h +64:vs31h +64:ppr +64:dscr +64:tar +64:bescr +64:ebbhr +64:ebbrr +64:mmcr0 +64:mmcr2 +64:siar +64:sdar +64:sier +64:tfhar +64:texasr +64:tfiar +64:cr0 +64:cr1 +64:cr2 +64:cr3 +64:cr4 +64:cr5 +64:cr6 +64:cr7 +64:cr8 +64:cr9 +64:cr10 +64:cr11 +64:cr12 +64:cr13 +64:cr14 +64:cr15 +64:cr16 +64:cr17 +64:cr18 +64:cr19 +64:cr20 +64:cr21 +64:cr22 +64:cr23 +64:cr24 +64:cr25 +64:cr26 +64:cr27 +64:cr28 +64:cr29 +64:cr30 +64:cr31 +32:ccr +32:cxer +64:clr +64:cctr +64:cf0 +64:cf1 +64:cf2 +64:cf3 +64:cf4 +64:cf5 +64:cf6 +64:cf7 +64:cf8 +64:cf9 +64:cf10 +64:cf11 +64:cf12 +64:cf13 +64:cf14 +64:cf15 +64:cf16 +64:cf17 +64:cf18 +64:cf19 +64:cf20 +64:cf21 +64:cf22 +64:cf23 +64:cf24 +64:cf25 +64:cf26 +64:cf27 +64:cf28 +64:cf29 +64:cf30 +64:cf31 +64:cfpscr +128:cvr0 +128:cvr1 +128:cvr2 +128:cvr3 +128:cvr4 +128:cvr5 +128:cvr6 +128:cvr7 +128:cvr8 +128:cvr9 +128:cvr10 +128:cvr11 +128:cvr12 +128:cvr13 +128:cvr14 +128:cvr15 +128:cvr16 +128:cvr17 +128:cvr18 +128:cvr19 +128:cvr20 +128:cvr21 +128:cvr22 +128:cvr23 +128:cvr24 +128:cvr25 +128:cvr26 +128:cvr27 +128:cvr28 +128:cvr29 +128:cvr30 +128:cvr31 +32:cvscr +32:cvrsave +64:cvs0h +64:cvs1h +64:cvs2h +64:cvs3h +64:cvs4h +64:cvs5h +64:cvs6h +64:cvs7h +64:cvs8h +64:cvs9h +64:cvs10h +64:cvs11h +64:cvs12h +64:cvs13h +64:cvs14h +64:cvs15h +64:cvs16h +64:cvs17h +64:cvs18h +64:cvs19h +64:cvs20h +64:cvs21h +64:cvs22h +64:cvs23h +64:cvs24h +64:cvs25h +64:cvs26h +64:cvs27h +64:cvs28h +64:cvs29h +64:cvs30h +64:cvs31h +64:cppr +64:cdscr +64:ctar diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 7e41d8ff731..504de3657e6 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -105,6 +105,22 @@ && (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; @@ -2322,6 +2338,11 @@ rs6000_register_name (struct gdbarch *gdbarch, int regno) && 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)) { @@ -2376,6 +2397,48 @@ rs6000_register_name (struct gdbarch *gdbarch, int 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); } @@ -2387,24 +2450,26 @@ 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)); - /* 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_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 (__FILE__, __LINE__, + _("rs6000_pseudo_register_type: " + "called on unexpected register '%s' (%d)"), + gdbarch_register_name (gdbarch, regnum), regnum); } /* The register format for RS/6000 floating point registers is always @@ -2580,25 +2645,35 @@ 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; + 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; @@ -2610,23 +2685,32 @@ 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; + 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); } } @@ -2636,30 +2720,43 @@ 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; + 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; @@ -2671,56 +2768,103 @@ 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; + 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; + 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; + 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); } @@ -2736,12 +2880,15 @@ rs6000_pseudo_register_read (struct gdbarch *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_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: " @@ -2761,12 +2908,15 @@ rs6000_pseudo_register_write (struct gdbarch *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_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: " @@ -2774,6 +2924,97 @@ rs6000_pseudo_register_write (struct gdbarch *gdbarch, gdbarch_register_name (gdbarch, reg_nr), 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); + 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; + } + + 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 registers that form the VSX or + checkpointed VSX pseudo-register REG_NR. */ + +static void +vsx_ax_pseudo_register_collect (struct gdbarch *gdbarch, + struct agent_expr *ax, int reg_nr) +{ + struct gdbarch_tdep *tdep = 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; + } + + 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) +{ + struct gdbarch_tdep *tdep = 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) @@ -2785,29 +3026,20 @@ rs6000_ax_pseudo_register_collect (struct gdbarch *gdbarch, 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)) + else if (IS_DFP_PSEUDOREG (tdep, reg_nr) + || IS_CDFP_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); + dfp_ax_pseudo_register_collect (gdbarch, ax, reg_nr); } - else if (IS_VSX_PSEUDOREG (tdep, reg_nr)) + else if (IS_VSX_PSEUDOREG (tdep, reg_nr) + || IS_CVSX_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); - } + vsx_ax_pseudo_register_collect (gdbarch, ax, reg_nr); } - else if (IS_EFP_PSEUDOREG (tdep, reg_nr)) + else if (IS_EFP_PSEUDOREG (tdep, reg_nr) + || IS_CEFP_PSEUDOREG (tdep, reg_nr)) { - int reg_index = reg_nr - tdep->ppc_efpr0_regnum; - ax_reg_mask (ax, tdep->ppc_vr0_regnum + reg_index); + efp_ax_pseudo_register_collect (gdbarch, ax, reg_nr); } else internal_error (__FILE__, __LINE__, @@ -5817,7 +6049,10 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) enum powerpc_elf_abi elf_abi = POWERPC_ELF_AUTO; 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; + 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; @@ -6216,6 +6451,201 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) } 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, + PPC_TFHAR_REGNUM + i, + tm_spr_regs[i]); + if (!valid_p) + { + tdesc_data_cleanup (tdesc_data); + 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, + PPC_CR0_REGNUM + i, + cgprs[i]); + if (!valid_p) + { + tdesc_data_cleanup (tdesc_data); + 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, + PPC_CF0_REGNUM + i, + cfprs[i]); + + if (!valid_p) + { + tdesc_data_cleanup (tdesc_data); + 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, + PPC_CVR0_REGNUM + i, + cvmx[i]); + + if (!valid_p) + { + tdesc_data_cleanup (tdesc_data); + 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, + (PPC_CVSR0_UPPER_REGNUM + + i), + cvsx[i]); + + if (!valid_p || !have_htm_fpu || !have_htm_altivec) + { + tdesc_data_cleanup (tdesc_data); + 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, + PPC_CPPR_REGNUM, "cppr"); + + if (!valid_p) + { + tdesc_data_cleanup (tdesc_data); + 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, + PPC_CDSCR_REGNUM, "cdscr"); + + if (!valid_p) + { + tdesc_data_cleanup (tdesc_data); + 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, + PPC_CTAR_REGNUM, "ctar"); + + if (!valid_p) + { + tdesc_data_cleanup (tdesc_data); + 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 @@ -6428,6 +6858,15 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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_fp0_regnum (gdbarch, tdep->ppc_fp0_regnum); @@ -6449,7 +6888,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) else tdep->lr_frame_offset = 4; - if (have_spe || have_dfp || have_vsx) + if (have_spe || have_dfp || have_vsx || have_htm_fpu || have_htm_vsx) { set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read); set_gdbarch_pseudo_register_write (gdbarch, @@ -6471,6 +6910,11 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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); @@ -6586,6 +7030,9 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->ppc_dl0_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); @@ -6606,6 +7053,18 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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_cooked_regs (gdbarch) == cur_reg); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index bb0293335c2..a8c83d792c1 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-10-26 Pedro Franco de Carvalho + + * gdb.arch/powerpc-htm-regs.c: New file. + * gdb.arch/powerpc-htm-regs.exp: New file. + 2018-10-26 Pedro Franco de Carvalho * gdb.arch/powerpc-tar.c: New file. diff --git a/gdb/testsuite/gdb.arch/powerpc-htm-regs.c b/gdb/testsuite/gdb.arch/powerpc-htm-regs.c new file mode 100644 index 00000000000..8c062ced314 --- /dev/null +++ b/gdb/testsuite/gdb.arch/powerpc-htm-regs.c @@ -0,0 +1,39 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright (C) 2018 Free Software Foundation, Inc. + + 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 . */ + +int main (void) +{ + /* Touch DSCR. Some kernels won't schedule the thread with a DSCR + altered by ptrace unless the register was used at some point. */ + unsigned long dscr = 0x0; + + /* This is the non-privileged SPR number to access DSCR, + available since isa 207. */ + asm volatile ("mtspr 3,%0" : : "r" (dscr)); + + asm volatile ("tbegin."); // first marker + asm volatile goto ("bc 12,2,%l[end]" + : + : + : + : end); + asm volatile ("tabort. 0"); +end: + asm volatile ("nop"); // second marker + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/powerpc-htm-regs.exp b/gdb/testsuite/gdb.arch/powerpc-htm-regs.exp new file mode 100644 index 00000000000..a1c876a1d14 --- /dev/null +++ b/gdb/testsuite/gdb.arch/powerpc-htm-regs.exp @@ -0,0 +1,328 @@ +# Copyright (C) 2018 Free Software Foundation, Inc. + +# 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 . + +# This file is part of the gdb testsuite. + +# Test access to HTM (Hardware Transactional Memory) registers. The +# tests read the values of various registers before stepping the +# inferior through a "tbegin." instruction to start a transaction, +# then the checkpointed versions of the registers are checked against +# the pre-transactional values. Then, new values are written to some +# of the checkpointed registers, these values are read back and saved, +# the inferior continues until the transaction aborts, and the regular +# registers are then checked against the saved values, because the +# abort should have reverted the registers to these values. + +if {![istarget "powerpc*-*-linux*"]} then { + verbose "Skipping PowerPC test for HTM registers." + return +} + +standard_testfile .c .gen.c + +# First check if our processor and kernel support access to +# the registers we need and to the HTM facility. + +proc check_register_access { regname } { + global gdb_prompt + + set test "$regname register access" + gdb_test_multiple "info reg $regname" "$test" { + -re "Invalid register.*\r\n$gdb_prompt $" { + unsupported "$test" + return 0 + } + -re "\r\n$regname.*\r\n$gdb_prompt $" { + pass "$test" + return 1 + } + } + return 0 +} + +proc check_htm_support {} { + global gdb_prompt + set test "htm support" + + gdb_test_multiple "stepi" "$test" { + -re "Illegal instruction.*\r\n$gdb_prompt $" { + unsupported $test + return 0 + } + -re "nop.*\r\n$gdb_prompt $" + { + pass $test + return 1 + } + } + return 0; +} + +with_test_prefix "check htm support" { + set gen_src [standard_output_file $srcfile2] + + gdb_produce_source $gen_src { + int main () { + asm volatile ("tbegin."); // marker + asm volatile ("nop"); + return 0; + } + } + + if {[build_executable "compile" $binfile $gen_src {debug}] == -1} { + return + } + + clean_restart $binfile + + # Displaced-stepping a tbegin. causes problems, + # so we make the breakpoint temporary. + gdb_breakpoint [gdb_get_line_number "marker" "$gen_src"] temporary + + gdb_run_cmd + + # Wait for the prompt. + if {[gdb_test "" "Temporary breakpoint.*"] != 0 } { + return + } + + # Make sure that we stopped at the right place (just before tbegin. is + # executed). + if { [gdb_test "x/i \$pc" "=> $hex.*:.*tbegin\\..*" "disassemble tbegin"] != 0} { + return + } + + if {![check_register_access "vs0"]} { + return + } + + if {![check_register_access "texasr"]} { + return + } + + if {![check_register_access "dscr"]} { + return + } + + if {![check_register_access "ppr"]} { + return + } + + if {![check_register_access "tar"]} { + return + } + + if {![check_htm_support]} { + return + } +} + +# Now do the actual test. +if {[build_executable "compile" $binfile $srcfile {debug}] == -1} { + return +} + +clean_restart $binfile + +gdb_breakpoint [gdb_get_line_number "first marker"] temporary + +gdb_run_cmd + +# Wait for the prompt. +gdb_test "" "Temporary breakpoint.*" + +if {[gdb_test "x/i \$pc" "=> $hex.*:.*tbegin\\..*" "disassemble tbegin"] != 0} { + return +} + +# Now we write non-zero values to some registers, then read the values +# of various registers, then stepi to start the transaction. The +# checkpointed register state should correspond to the values we read. + +# Write to the GPRs +for {set i 0} {$i < 32} {incr i 1} { + gdb_test_no_output "set \$r$i = $i" +} + +gdb_test_no_output "set \$xer = 0xc0000000" + +# FPRs +gdb_test_no_output "set \$f0 = 0.5" +for {set i 1} {$i < 32} {incr i 1} { + gdb_test_no_output "set \$f$i = \$f[expr $i - 1] + 1.0" +} + +gdb_test_no_output "set \$fpscr = 0x84005000" + +# VRs +for {set i 0} {$i < 32} {incr i 1} { + for {set j 0} {$j < 4} {incr j 1} { + gdb_test_no_output "set \$vr$i.v4_int32\[$j\] = $i" + } +} + +gdb_test_no_output "set \$dscr = 0x2" +gdb_test_no_output "set \$tar = &main" "set tar" + +# Get the pre-transactional value of the registers. +for {set i 0} {$i < 32} {incr i 1} { + set "r$i" [get_hexadecimal_valueof "\$r$i" "default0"] +} + +set cr [get_hexadecimal_valueof "\$cr" "default0"] +set xer [get_hexadecimal_valueof "\$xer" "default0"] +set lr [get_hexadecimal_valueof "\$lr" "default0"] +set ctr [get_hexadecimal_valueof "\$ctr" "default0"] + +for {set i 0} {$i < 32} {incr i 1} { + set "f$i" [get_valueof "" "\$f$i" "default0"] +} + +set fpscr [get_hexadecimal_valueof "\$fpscr" "default0"] + +for {set i 0} {$i < 32} {incr i 1} { + set "vr$i" [get_hexadecimal_valueof "\$vr$i.uint128" "default0"] +} + +set vscr [get_hexadecimal_valueof "\$vscr" "default0"] +set vrsave [get_hexadecimal_valueof "\$vrsave" "default0"] + +for {set i 0} {$i < 64} {incr i 1} { + set "vs$i" [get_hexadecimal_valueof "\$vs$i.uint128" "default0"] +} + +set dscr [get_hexadecimal_valueof "\$dscr" "default0"] +set ppr [get_hexadecimal_valueof "\$ppr" "default0"] +set tar [get_hexadecimal_valueof "\$tar" "default0"] + +gdb_test "stepi" "asm.*bc.*" + +proc test_register_match {reg_name reg_var_name hex} { + set test "$reg_name matches $reg_var_name" + + # In some infrequent cases CXER doesn't match the + # pre-transactional XER, possibly due to a linux kernel bug. + set should_xfail 0 + if [istarget "powerpc*-*-linux*" && reg_name == "cxer"] { + set should_xfail 1 + } + + upvar $reg_var_name expected_val + + if {$hex} { + set actual_val [get_hexadecimal_valueof "\$$reg_name" "default1"] + } else { + set actual_val [get_valueof "" "\$$reg_name" "default1"] + } + + if { "$expected_val" == "$actual_val" } { + pass $test + } else { + if {$should_xfail} { + xfail $test + } else { + fail $test + } + } +} + +for {set i 0} {$i < 32} {incr i 1} { + test_register_match "cr$i" "r$i" 1 +} + +test_register_match "ccr" "cr" 1 +test_register_match "cxer" "xer" 1 +test_register_match "clr" "lr" 1 +test_register_match "cctr" "ctr" 1 + +for {set i 0} {$i < 32} {incr i 1} { + test_register_match "cf$i" "f$i" 0 +} + +test_register_match "cfpscr" "fpscr" 1 + +for {set i 0} {$i < 32} {incr i 1} { + test_register_match "cvr$i.uint128" "vr$i" 1 +} + +test_register_match "cvscr" "vscr" 1 +test_register_match "cvrsave" "vrsave" 1 + +for {set i 0} {$i < 64} {incr i 1} { + test_register_match "cvs$i.uint128" "vs$i" 1 +} + +test_register_match "cdscr" "dscr" 1 +test_register_match "cppr" "ppr" 1 +test_register_match "ctar" "tar" 1 + +# Support for writing to the checkpointed registers is not +# currently available in the gdbserver stub. +if [target_is_gdbserver] { + unsupported "write to checkpointed registers" + return +} + +# Now write different values to some of the checkpointed registers and +# check that the transaction abort reverts the register to these +# values. +for {set i 0} {$i < 32} {incr i 1} { + gdb_test_no_output "set \$cr$i = $i + 0xC00" +} + +gdb_test_no_output "set \$cf0 = 0.25" +for {set i 1} {$i < 32} {incr i 1} { + gdb_test_no_output "set \$cf$i = \$cf[expr $i - 1] + 1.0" +} + +for {set i 0} {$i < 32} {incr i 1} { + for {set j 0} {$j < 4} {incr j 1} { + gdb_test_no_output "set \$cvr$i.v4_int32\[$j\] = $i + 0xF00" + } +} + +# Read back the values. +with_test_prefix "after write" { + for {set i 0} {$i < 32} {incr i 1} { + set "cr$i" [get_hexadecimal_valueof "\$cr$i" "default0"] + } + + for {set i 0} {$i < 32} {incr i 1} { + set "cf$i" [get_valueof "" "\$cf$i" "default0"] + } + + for {set i 0} {$i < 64} {incr i 1} { + set "cvs$i" [get_hexadecimal_valueof "\$cvs$i.uint128" "default0"] + } +} + +gdb_breakpoint [gdb_get_line_number "second marker"] + +gdb_test "continue" + +with_test_prefix "after transaction failure" { + for {set i 0} {$i < 32} {incr i 1} { + test_register_match "r$i" "cr$i" 1 + } + + for {set i 0} {$i < 32} {incr i 1} { + test_register_match "f$i" "cf$i" 0 + } + + for {set i 0} {$i < 64} {incr i 1} { + test_register_match "vs$i.uint128" "cvs$i" 1 + } +} +