+2019-01-14 Pedro Franco de Carvalho <pedromfc@linux.ibm.com>
+
+ * ppc-tdep.h (struct gdbarch_tdep) <ppc_v0_alias_regnum>: New
+ field.
+ * rs6000-tdep.c: Include reggroups.h.
+ (IS_V_ALIAS_PSEUDOREG): Define.
+ (rs6000_register_name): Return names for the "vX" aliases.
+ (rs6000_pseudo_register_type): Return type for the "vX" aliases.
+ (rs6000_pseudo_register_reggroup_p): Restore. Handle "vX"
+ aliases. Call default_register_reggroup_p for all other
+ pseudo-registers.
+ (v_alias_pseudo_register_read, v_alias_pseudo_register_write):
+ New functions.
+ (rs6000_pseudo_register_read, rs6000_pseudo_register_write):
+ Handle "vX" aliases.
+ (v_alias_pseudo_register_collect): New function.
+ (rs6000_ax_pseudo_register_collect): Handle "vX" aliases.
+ (rs6000_gdbarch_init): Initialize "vX" aliases as
+ pseudo-registers. Restore registration of
+ rs6000_pseudo_register_reggroup_p with
+ set_tdesc_pseudo_register_reggroup_p.
+
2019-01-13 Max Filippov <jcmvbkbc@gmail.com>
* xtensa-linux-tdep.c (xtensa_linux_init_abi): Update
+2019-01-14 Pedro Franco de Carvalho <pedromfc@linux.ibm.com>
+
+ * gdb.texinfo (PowerPC Features): Document the alias
+ pseudo-registers for the org.gnu.gdb.power.altivec feature.
+
2019-01-09 Simon Marchi <simon.marchi@ericsson.com>
* gdb.texinfo (Print Settings): Remove mention of specific
contain registers @samp{f0} through @samp{f31} and @samp{fpscr}.
The @samp{org.gnu.gdb.power.altivec} feature is optional. It should
-contain registers @samp{vr0} through @samp{vr31}, @samp{vscr},
-and @samp{vrsave}.
+contain registers @samp{vr0} through @samp{vr31}, @samp{vscr}, and
+@samp{vrsave}. @value{GDBN} will define pseudo-registers @samp{v0}
+through @samp{v31} as aliases for the corresponding @samp{vrX}
+registers.
The @samp{org.gnu.gdb.power.vsx} feature is optional. It should
contain registers @samp{vs0h} through @samp{vs31h}. @value{GDBN} will
int ppc_vr0_regnum; /* First AltiVec register. */
int ppc_vrsave_regnum; /* Last AltiVec register. */
+ /* Altivec pseudo-register vX aliases for the raw vrX
+ registers. */
+ int ppc_v0_alias_regnum;
+
/* SPE registers. */
int ppc_ev0_upper_regnum; /* First GPR upper half register. */
int ppc_ev0_regnum; /* First ev register. */
#include "infcall.h"
#include "sim-regno.h"
#include "gdb/sim-ppc.h"
+#include "reggroups.h"
#include "dwarf2-frame.h"
#include "target-descriptions.h"
#include "user-regs.h"
&& (regnum) >= (tdep)->ppc_dl0_regnum \
&& (regnum) < (tdep)->ppc_dl0_regnum + 16)
+/* Determine if regnum is a "vX" alias for the raw "vrX" vector
+ registers. */
+#define IS_V_ALIAS_PSEUDOREG(tdep, regnum) (\
+ (tdep)->ppc_v0_alias_regnum >= 0 \
+ && (regnum) >= (tdep)->ppc_v0_alias_regnum \
+ && (regnum) < (tdep)->ppc_v0_alias_regnum + ppc_num_vrs)
+
/* Determine if regnum is a POWER7 VSX register. */
#define IS_VSX_PSEUDOREG(tdep, regnum) ((tdep)->ppc_vsr0_regnum >= 0 \
&& (regnum) >= (tdep)->ppc_vsr0_regnum \
return dfp128_regnames[regno - tdep->ppc_dl0_regnum];
}
+ /* Check if this is a vX alias for a raw vrX vector register. */
+ if (IS_V_ALIAS_PSEUDOREG (tdep, regno))
+ {
+ static const char *const vector_alias_regnames[] = {
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
+ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
+ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
+ };
+ return vector_alias_regnames[regno - tdep->ppc_v0_alias_regnum];
+ }
+
/* Check if this is a VSX pseudo-register. */
if (IS_VSX_PSEUDOREG (tdep, regno))
{
|| IS_CDFP_PSEUDOREG (tdep, regnum))
/* PPC decimal128 pseudo-registers. */
return builtin_type (gdbarch)->builtin_declong;
+ else if (IS_V_ALIAS_PSEUDOREG (tdep, regnum))
+ return gdbarch_register_type (gdbarch,
+ tdep->ppc_vr0_regnum
+ + (regnum
+ - tdep->ppc_v0_alias_regnum));
else if (IS_VSX_PSEUDOREG (tdep, regnum)
|| IS_CVSX_PSEUDOREG (tdep, regnum))
/* POWER7 VSX pseudo-registers. */
gdbarch_register_name (gdbarch, regnum), regnum);
}
+/* Check if REGNUM is a member of REGGROUP. We only need to handle
+ the vX aliases for the vector registers by always returning false
+ to avoid duplicated information in "info register vector/all",
+ since the raw vrX registers will already show in these cases. For
+ other pseudo-registers we use the default membership function. */
+
+static int
+rs6000_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+ struct reggroup *group)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (IS_V_ALIAS_PSEUDOREG (tdep, regnum))
+ return 0;
+ else
+ return default_register_reggroup_p (gdbarch, regnum, group);
+}
+
/* The register format for RS/6000 floating point registers is always
double, we need a conversion if the memory format is float. */
}
}
+/* Read method for the vX aliases for the raw vrX registers. */
+
+static enum register_status
+v_alias_pseudo_register_read (struct gdbarch *gdbarch,
+ readable_regcache *regcache, int reg_nr,
+ gdb_byte *buffer)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
+
+ return regcache->raw_read (tdep->ppc_vr0_regnum
+ + (reg_nr - tdep->ppc_v0_alias_regnum),
+ buffer);
+}
+
+/* Write method for the vX aliases for the raw vrX registers. */
+
+static void
+v_alias_pseudo_register_write (struct gdbarch *gdbarch,
+ struct regcache *regcache,
+ int reg_nr, const gdb_byte *buffer)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
+
+ regcache->raw_write (tdep->ppc_vr0_regnum
+ + (reg_nr - tdep->ppc_v0_alias_regnum), buffer);
+}
+
/* Read method for POWER7 VSX pseudo-registers. */
static enum register_status
vsx_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
else if (IS_DFP_PSEUDOREG (tdep, reg_nr)
|| IS_CDFP_PSEUDOREG (tdep, reg_nr))
return dfp_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
+ else if (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr))
+ return v_alias_pseudo_register_read (gdbarch, regcache, reg_nr,
+ buffer);
else if (IS_VSX_PSEUDOREG (tdep, reg_nr)
|| IS_CVSX_PSEUDOREG (tdep, reg_nr))
return vsx_pseudo_register_read (gdbarch, regcache, reg_nr, buffer);
else if (IS_DFP_PSEUDOREG (tdep, reg_nr)
|| IS_CDFP_PSEUDOREG (tdep, reg_nr))
dfp_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
+ else if (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr))
+ v_alias_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
else if (IS_VSX_PSEUDOREG (tdep, reg_nr)
|| IS_CVSX_PSEUDOREG (tdep, reg_nr))
vsx_pseudo_register_write (gdbarch, regcache, reg_nr, buffer);
ax_reg_mask (ax, fp0 + 2 * reg_index + 1);
}
+/* Set the register mask in AX with the raw vector register that
+ corresponds to its REG_NR alias. */
+
+static void
+v_alias_pseudo_register_collect (struct gdbarch *gdbarch,
+ struct agent_expr *ax, int reg_nr)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ gdb_assert (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr));
+
+ ax_reg_mask (ax, tdep->ppc_vr0_regnum
+ + (reg_nr - tdep->ppc_v0_alias_regnum));
+}
+
/* Set the register mask in AX with the registers that form the VSX or
checkpointed VSX pseudo-register REG_NR. */
{
dfp_ax_pseudo_register_collect (gdbarch, ax, reg_nr);
}
+ else if (IS_V_ALIAS_PSEUDOREG (tdep, reg_nr))
+ {
+ v_alias_pseudo_register_collect (gdbarch, ax, reg_nr);
+ }
else if (IS_VSX_PSEUDOREG (tdep, reg_nr)
|| IS_CVSX_PSEUDOREG (tdep, reg_nr))
{
else
tdep->lr_frame_offset = 4;
- if (have_spe || have_dfp || have_vsx || have_htm_fpu || have_htm_vsx)
+ if (have_spe || have_dfp || have_altivec
+ || have_vsx || have_htm_fpu || have_htm_vsx)
{
set_gdbarch_pseudo_register_read (gdbarch, rs6000_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch,
num_pseudoregs += 32;
if (have_dfp)
num_pseudoregs += 16;
+ if (have_altivec)
+ num_pseudoregs += 32;
if (have_vsx)
/* Include both VSX and Extended FP registers. */
num_pseudoregs += 96;
}
set_tdesc_pseudo_register_type (gdbarch, rs6000_pseudo_register_type);
+ set_tdesc_pseudo_register_reggroup_p (gdbarch,
+ rs6000_pseudo_register_reggroup_p);
tdesc_use_registers (gdbarch, tdesc, tdesc_data);
/* Override the normal target description method to make the SPE upper
/* Choose register numbers for all supported pseudo-registers. */
tdep->ppc_ev0_regnum = -1;
tdep->ppc_dl0_regnum = -1;
+ tdep->ppc_v0_alias_regnum = -1;
tdep->ppc_vsr0_regnum = -1;
tdep->ppc_efpr0_regnum = -1;
tdep->ppc_cdl0_regnum = -1;
tdep->ppc_dl0_regnum = cur_reg;
cur_reg += 16;
}
+ if (have_altivec)
+ {
+ tdep->ppc_v0_alias_regnum = cur_reg;
+ cur_reg += 32;
+ }
if (have_vsx)
{
tdep->ppc_vsr0_regnum = cur_reg;
+2019-01-14 Pedro Franco de Carvalho <pedromfc@linux.ibm.com>
+
+ * gdb.arch/vsx-regs.exp: Add tests that use the vector register
+ aliases.
+ * gdb.arch/altivec-regs.exp: Likewise. Fix indentation of two
+ tests.
+ * gdb.arch/powerpc-vector-regs.c: New file.
+ * gdb.arch/powerpc-vector-regs.exp: New file.
+
2019-01-14 Pedro Franco de Carvalho <pedromfc@linux.ibm.com>
* gdb.arch/altivec-regs.exp: Fix the list passed to
}
for {set i 0} {$i < 32} {incr i 1} {
- gdb_test "info reg vr$i" "vr$i.*$vector_register" "info reg vr$i"
+ gdb_test "info reg vr$i" "vr$i.*$vector_register" "info reg vr$i"
+ gdb_test "info reg v$i" "v$i.*$vector_register" "info reg v$i"
}
gdb_test "info reg vrsave" "vrsave.*0x1\[ \t\]+1" "info reg vrsave"
}
for {set i 0} {$i < 32} {incr i 1} {
- gdb_test "print \$vr$i" ".* = $decimal_vector" "print vr$i"
+ gdb_test "print \$vr$i" ".* = $decimal_vector" "print vr$i"
+ gdb_test "print \$v$i" ".* = $decimal_vector" "print v$i"
}
gdb_test "print \$vrsave" ".* = 1" "print vrsave"
--- /dev/null
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright (C) 2019 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 <http://www.gnu.org/licenses/>. */
+
+/* Write bytes with values ranging from 0 to 31 to each byte of each
+ corresponding vector register. */
+int main (void)
+{
+ asm volatile ("vspltisb 0, 0" : : : "v0");
+ asm volatile ("vspltisb 1, 1" : : : "v1");
+
+ asm volatile ("vaddubm 2, 1, 1" : : : "v2");
+ asm volatile ("vaddubm 3, 2, 1" : : : "v3");
+ asm volatile ("vaddubm 4, 3, 1" : : : "v4");
+ asm volatile ("vaddubm 5, 4, 1" : : : "v5");
+ asm volatile ("vaddubm 6, 5, 1" : : : "v6");
+ asm volatile ("vaddubm 7, 6, 1" : : : "v7");
+ asm volatile ("vaddubm 8, 7, 1" : : : "v8");
+ asm volatile ("vaddubm 9, 8, 1" : : : "v9");
+ asm volatile ("vaddubm 10, 9, 1" : : : "v10");
+ asm volatile ("vaddubm 11, 10, 1" : : : "v11");
+ asm volatile ("vaddubm 12, 11, 1" : : : "v12");
+ asm volatile ("vaddubm 13, 12, 1" : : : "v13");
+ asm volatile ("vaddubm 14, 13, 1" : : : "v14");
+ asm volatile ("vaddubm 15, 14, 1" : : : "v15");
+ asm volatile ("vaddubm 16, 15, 1" : : : "v16");
+ asm volatile ("vaddubm 17, 16, 1" : : : "v17");
+ asm volatile ("vaddubm 18, 17, 1" : : : "v18");
+ asm volatile ("vaddubm 19, 18, 1" : : : "v19");
+ asm volatile ("vaddubm 20, 19, 1" : : : "v20");
+ asm volatile ("vaddubm 21, 20, 1" : : : "v21");
+ asm volatile ("vaddubm 22, 21, 1" : : : "v22");
+ asm volatile ("vaddubm 23, 22, 1" : : : "v23");
+ asm volatile ("vaddubm 24, 23, 1" : : : "v24");
+ asm volatile ("vaddubm 25, 24, 1" : : : "v25");
+ asm volatile ("vaddubm 26, 25, 1" : : : "v26");
+ asm volatile ("vaddubm 27, 26, 1" : : : "v27");
+ asm volatile ("vaddubm 28, 27, 1" : : : "v28");
+ asm volatile ("vaddubm 29, 28, 1" : : : "v29");
+ asm volatile ("vaddubm 30, 29, 1" : : : "v30");
+ asm volatile ("vaddubm 31, 30, 1" : : : "v31");
+
+ asm volatile ("nop"); // marker
+
+ return 0;
+}
--- /dev/null
+# Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
+
+# This file is part of the gdb testsuite.
+
+# Test vector register access on Power. The inferior executes
+# instructions that fill the vector registers with values ranging from
+# 0 to 31 in each of the 16 bytes of each corresponding register, and
+# we then check if gdb sees these same values.
+
+if {![istarget "powerpc*"] || [skip_altivec_tests]} {
+ verbose "Skipping PowerPC vector register tests."
+ return
+}
+
+standard_testfile
+
+if { [gdb_compile ${srcdir}/${subdir}/${srcfile} ${binfile} executable {debug}] != "" } {
+ untested "vector register tests for PowerPC"
+ return
+}
+
+# Check if our test binary can actually run on this processor.
+clean_restart ${binfile}
+
+gdb_run_cmd
+
+gdb_test_multiple "" "wait for exit" {
+ -re ".*Illegal instruction.*${gdb_prompt} $" {
+ unsupported "vector register tests for PowerPC"
+ return
+ }
+ -re ".*$inferior_exited_re normally.*${gdb_prompt} $" {
+ }
+}
+
+# Run the actual test.
+clean_restart ${binfile}
+
+gdb_breakpoint [gdb_get_line_number "marker"]
+
+gdb_run_cmd
+
+# Wait for the prompt.
+gdb_test "" "Breakpoint.*at.*" "wait for prompt"
+
+for {set i 0} {$i < 32} {incr i 1} {
+ gdb_test "p/z \$vr$i.uint128" ".* = 0x(0?[format %x $i]){16}.*"
+ gdb_test "p/z \$v$i.uint128" ".* = 0x(0?[format %x $i]){16}.*"
+}
for {set i 0} {$i < 32} {incr i 1} {
gdb_test "info reg vr$i" "vr$i.*$vector_register3_vr" "info reg vr$i"
+ gdb_test "info reg v$i" "v$i.*$vector_register3_vr" "info reg v$i"
}
# Create a core file. We create the core file before the F32~F63/VR0~VR31 test
for {set i 0} {$i < 32} {incr i 1} {
gdb_test "info reg vr$i" "vr$i.*$vector_register1_vr" "info reg vr$i (doubleword 0)"
+ gdb_test "info reg v$i" "v$i.*$vector_register1_vr" "info reg v$i (doubleword 0)"
}
# 2: Set VR0~VR31 registers and check if it reflects on F32~F63.
for {set i 0} {$i < 32} {incr i 1} {
gdb_test "info reg vr$i" "vr$i.*$vector_register2_vr" "info reg vr$i (doubleword 1)"
+ gdb_test "info reg v$i" "v$i.*$vector_register2_vr" "info reg v$i (doubleword 1)"
}
# Test reading the core file.