@@ -43343,8 +43343,10 @@ The @samp{org.gnu.gdb.power.fpu} feature is optional. It should
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
@@ -244,6 +244,10 @@ struct gdbarch_tdep
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. */
@@ -36,6 +36,7 @@
#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"
@@ -95,6 +96,13 @@
&& (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 \
@@ -2370,6 +2378,18 @@ rs6000_register_name (struct gdbarch *gdbarch, int regno)
return dfp128_regnames[regno - tdep->ppc_dl0_regnum];
}
+ /* Check if this is a vX alias for a raw vrX vector register. */
+ if (IS_V_ALIAS_PSEUDOREG (tdep, regno))
+ {
+ static const char *const vector_alias_regnames[] = {
+ "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
+ "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
+ "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
+ "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31"
+ };
+ return vector_alias_regnames[regno - tdep->ppc_v0_alias_regnum];
+ }
+
/* Check if this is a VSX pseudo-register. */
if (IS_VSX_PSEUDOREG (tdep, regno))
{
@@ -2460,6 +2480,11 @@ rs6000_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
|| 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. */
@@ -2475,6 +2500,24 @@ rs6000_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
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. */
@@ -2717,6 +2760,35 @@ dfp_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
}
}
+/* 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,
@@ -2886,6 +2958,9 @@ rs6000_pseudo_register_read (struct gdbarch *gdbarch,
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);
@@ -2914,6 +2989,8 @@ rs6000_pseudo_register_write (struct gdbarch *gdbarch,
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);
@@ -2954,6 +3031,20 @@ dfp_ax_pseudo_register_collect (struct gdbarch *gdbarch,
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. */
@@ -3034,6 +3125,10 @@ rs6000_ax_pseudo_register_collect (struct gdbarch *gdbarch,
{
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))
{
@@ -6891,7 +6986,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
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,
@@ -6910,6 +7006,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
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;
@@ -7022,6 +7120,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
}
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
@@ -7031,6 +7131,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
/* 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;
@@ -7049,6 +7150,11 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
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;
@@ -91,7 +91,8 @@ set vector_register ".uint128 = 0x1000000010000000100000001, v4_float = .0x0, 0x
}
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"
@@ -110,7 +111,8 @@ if {$endianness == "big"} {
}
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"
new file mode 100644
@@ -0,0 +1,59 @@
+/* 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;
+}
new file mode 100644
@@ -0,0 +1,62 @@
+# 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}.*"
+}
@@ -136,6 +136,7 @@ for {set i 32} {$i < 64} {incr i 1} {
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
@@ -155,6 +156,7 @@ for {set i 32} {$i < 64} {incr i 1} {
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.
@@ -170,6 +172,7 @@ for {set i 32} {$i < 64} {incr i 1} {
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.