gdb/gdb-rhbz1870031-p10-prefixed-insn-2of3.patch
Keith Seitz 4748efc8fa Backport "PowerPC remove 512 bytes region limit if 2nd DAWR is available"
(Rogerio Alves, RHBZ 1870029)
Backport patches for "Support prefixed instructions in GDB"
(Will Schmidt and Luis Machado, RHBZ 1870031)

Resolves: rhbz#1870029
Resolves: rhbz#1870031
2021-06-28 18:37:39 -04:00

634 lines
22 KiB
Diff

From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
From: Keith Seitz <keiths@redhat.com>
Date: Thu, 6 May 2021 14:53:00 -0400
Subject: gdb-rhbz1870031-p10-prefixed-insn-2of3.patch
;; Backport "gdb-power10-single-step"
;; (Will Schmidt, RHBZ 1870031)
commit c8a379440e0f8bf94ed5730e823c9256e64bf37c
Author: Will Schmidt <will_schmidt@vnet.ibm.com>
Date: Mon Apr 12 14:11:02 2021 -0500
[PATCH] gdb-power10-single-step
Hi,
This is based on a patch originally written by Alan Modra.
Powerpc / Power10 ISA 3.1 adds prefixed instructions, which
are 8 bytes in length. This is in contrast to powerpc previously
always having 4 byte instruction length. This patch implements
changes to allow GDB to better detect prefixed instructions, and
handle single stepping across the 8 byte instructions.
Added #defines to help test for PNOP and prefix instructions.
Update ppc_displaced_step_copy_insn() to handle pnop and prefixed
instructions whem R=0 (non-pc-relative).
Updated ppc_displaced_step_fixup() to properly handle the offset
value matching the current instruction size
Updated the for-loop within ppc_deal_with_atomic_sequence() to
count instructions properly in case we have a mix of 4-byte and
8-byte instructions within the atomic_sequence_length.
Added testcase and harness to exercise pc-relative load/store
instructions with R=0.
2021-04-12 Will Schmidt <will_schmidt@vnet.ibm.com>
gdb/ChangeLog:
* rs6000-tdep.c: Add support for single-stepping of
prefixed instructions.
gdb/testsuite/ChangeLog:
* gdb.arch/powerpc-plxv-nonrel.s: Testcase using
non-relative plxv instructions.
* gdb.arch/powerpc-plxv-nonrel.exp: Testcase harness.
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -814,7 +814,7 @@ typedef BP_MANIPULATION_ENDIAN (little_breakpoint, big_breakpoint)
rs6000_breakpoint;
/* Instruction masks for displaced stepping. */
-#define BRANCH_MASK 0xfc000000
+#define OP_MASK 0xfc000000
#define BP_MASK 0xFC0007FE
#define B_INSN 0x48000000
#define BC_INSN 0x40000000
@@ -842,6 +842,11 @@ typedef BP_MANIPULATION_ENDIAN (little_breakpoint, big_breakpoint)
#define ADDPCIS_TARGET_REGISTER 0x03F00000
#define ADDPCIS_INSN_REGSHIFT 21
+#define PNOP_MASK 0xfff3ffff
+#define PNOP_INSN 0x07000000
+#define R_MASK 0x00100000
+#define R_ZERO 0x00000000
+
/* Check if insn is one of the Load And Reserve instructions used for atomic
sequences. */
#define IS_LOAD_AND_RESERVE_INSN(insn) ((insn & LOAD_AND_RESERVE_MASK) == LWARX_INSTRUCTION \
@@ -873,10 +878,38 @@ ppc_displaced_step_copy_insn (struct gdbarch *gdbarch,
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int insn;
- read_memory (from, buf, len);
+ len = target_read (current_inferior()->top_target(), TARGET_OBJECT_MEMORY, NULL,
+ buf, from, len);
+ if ((ssize_t) len < PPC_INSN_SIZE)
+ memory_error (TARGET_XFER_E_IO, from);
insn = extract_signed_integer (buf, PPC_INSN_SIZE, byte_order);
+ /* Check for PNOP and for prefixed instructions with R=0. Those
+ instructions are safe to displace. Prefixed instructions with R=1
+ will read/write data to/from locations relative to the current PC.
+ We would not be able to fixup after an instruction has written data
+ into a displaced location, so decline to displace those instructions. */
+ if ((insn & OP_MASK) == 1 << 26)
+ {
+ if (((insn & PNOP_MASK) != PNOP_INSN)
+ && ((insn & R_MASK) != R_ZERO))
+ {
+ fprintf_unfiltered (gdb_stdlog,
+ "displaced: {ppc} Not displacing prefixed "
+ "instruction %08x at %s",
+ insn, paddress (gdbarch, from));
+ return NULL;
+ }
+ }
+ else
+ /* Non-prefixed instructions.. */
+ {
+ /* Set the instruction length to 4 to match the actual instruction
+ length. */
+ len = 4;
+ }
+
/* Assume all atomic sequences start with a Load and Reserve instruction. */
if (IS_LOAD_AND_RESERVE_INSN (insn))
{
@@ -917,11 +950,17 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch,
ppc_displaced_step_closure *closure = (ppc_displaced_step_closure *) closure_;
ULONGEST insn = extract_unsigned_integer (closure->buf.data (),
PPC_INSN_SIZE, byte_order);
- ULONGEST opcode = 0;
+ ULONGEST opcode;
/* Offset for non PC-relative instructions. */
- LONGEST offset = PPC_INSN_SIZE;
+ LONGEST offset;
- opcode = insn & BRANCH_MASK;
+ opcode = insn & OP_MASK;
+
+ /* Set offset to 8 if this is an 8-byte (prefixed) instruction. */
+ if ((opcode) == 1 << 26)
+ offset = 2 * PPC_INSN_SIZE;
+ else
+ offset = PPC_INSN_SIZE;
if (debug_displaced)
fprintf_unfiltered (gdb_stdlog,
@@ -1058,13 +1097,16 @@ ppc_deal_with_atomic_sequence (struct regcache *regcache)
instructions. */
for (insn_count = 0; insn_count < atomic_sequence_length; ++insn_count)
{
- loc += PPC_INSN_SIZE;
+ if ((insn & OP_MASK) == 1 << 26)
+ loc += 2 * PPC_INSN_SIZE;
+ else
+ loc += PPC_INSN_SIZE;
insn = read_memory_integer (loc, PPC_INSN_SIZE, byte_order);
/* Assume that there is at most one conditional branch in the atomic
sequence. If a conditional branch is found, put a breakpoint in
its destination address. */
- if ((insn & BRANCH_MASK) == BC_INSN)
+ if ((insn & OP_MASK) == BC_INSN)
{
int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000;
int absolute = insn & 2;
@@ -7095,7 +7137,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_displaced_step_location (gdbarch,
displaced_step_at_entry_point);
- set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE);
+ set_gdbarch_max_insn_length (gdbarch, 2 * PPC_INSN_SIZE);
/* Hook in ABI-specific overrides, if they have been registered. */
info.target_desc = tdesc;
diff --git a/gdb/testsuite/gdb.arch/powerpc-addpcis.exp b/gdb/testsuite/gdb.arch/powerpc-addpcis.exp
new file mode 100644
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-addpcis.exp
@@ -0,0 +1,104 @@
+# Copyright 2021 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/>.
+
+
+# Test to confirm that gdb is properly single stepping over the
+# displaced addpcis instruction.
+# The addpcis instruction and its extended mnemonics lnia and subpcis
+# apply an immediate shifted value (X || 0x0000) to the current PC/NIA
+# value, and store that value into the instructions target register.
+# When the instruction is displaced, it needs special handling.
+
+# lnia Rx == addpcis Rx,0
+# subcis Rx,value == addpcis Rx,-value
+
+if { ![istarget powerpc*-*] } {
+ verbose "Skipping powerpc addpcis test."
+ return
+}
+
+set retval 0
+
+standard_testfile .s
+
+if { [prepare_for_testing "failed to prepare" $testfile "$srcfile" \
+ {debug quiet}] } {
+ return -1
+}
+
+if ![runto_main] then {
+ return
+}
+
+set check_pc [get_hexadecimal_valueof "\$pc" "default0"]
+set bp1 *$check_pc+4
+set bp2 *$check_pc+12
+set bp3 *$check_pc+16
+gdb_breakpoint $bp1
+gdb_breakpoint $bp2
+gdb_breakpoint $bp3
+
+gdb_test "stepi" "" "set r3 "
+set check_r3 [get_hexadecimal_valueof "\$r3" "default0"]
+gdb_test "stepi" "" "set r4"
+set check_r4 [get_hexadecimal_valueof "\$r4" "default0"]
+gdb_test "stepi" "" "set r5"
+set check_r5 [get_hexadecimal_valueof "\$r5" "default0"]
+gdb_test "stepi" "" "set r6"
+set check_r6 [get_hexadecimal_valueof "\$r6" "default0"]
+gdb_test "stepi" "" "set r7"
+set check_r7 [get_hexadecimal_valueof "\$r7" "default0"]
+gdb_test "stepi" "" "set r8"
+set check_r8 [get_hexadecimal_valueof "\$r8" "default0"]
+gdb_test "stepi" "" "set r9"
+set check_r9 [get_hexadecimal_valueof "\$r9" "default0"]
+
+# R6 will contain the reference value. All other
+# instructions in this test will be storing values
+# relative to what is stored in R6.
+
+# subpcis 3,+0x100 # /* set r3 */
+# subpcis 4,+0x10 # /* set r4 */
+# subpcis 5,+0x1 # /* set r5 */
+# lnia 6 # /* set r6 */
+# addpcis 7,+0x1 # /* set r7 */
+# addpcis 8,+0x10 # /* set r8 */
+# addpcis 9,+0x100 # /* set r9 */
+
+if [expr $check_r3 + 0x1000000 != $check_r6 - 0xc ] {
+ fail "unexpected value r3 + 0x1,000,000 != r6 + 0xc ; r3: $check_r3 r6: $check_r6 "
+}
+if [expr $check_r4 + 0x100000 != $check_r6 - 0x8 ] {
+ fail "unexpected value r4 + 0x100,000 != r6 - 0x8 ; r4: $check_r4 r6: $check_r6 "
+}
+if [expr $check_r5 + 0x10000 != $check_r6 - 0x4 ] {
+ fail "unexpected value r5 + 0x10,000 != r6 , r5: $check_r5 r6: $check_r6 "
+}
+if [expr $check_r6 != $check_r6] {
+ fail "unexpected value r6 != r6 , r6: $check_r6 r6: $check_r6 "
+}
+if [expr $check_r7 - 0x10000 != $check_r6 + 0x4] {
+ fail "unexpected value r7 - 0x10,000 != r6 + 0x4 , r7: $check_r7 r7: $check_r6 "
+}
+if [expr $check_r8 - 0x100000 != $check_r6 + 0x8 ] {
+ fail "unexpected value r8 - 0x100,000 != r6 , r8: $check_r8 r8: $check_r6 "
+}
+if [expr $check_r9 - 0x1000000 != $check_r6 + 0xc ] {
+ fail "unexpected value r9 - 0x1,000,000 != r6 + 0xc , r9: $check_r9 r6: $check_r6 "
+}
+
+gdb_test "info break"
+gdb_test "info register r3 r4 r5 r6 r7 r8 r9"
+gdb_test "disas main"
diff --git a/gdb/testsuite/gdb.arch/powerpc-addpcis.s b/gdb/testsuite/gdb.arch/powerpc-addpcis.s
new file mode 100644
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-addpcis.s
@@ -0,0 +1,33 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2021 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/>. */
+
+
+/* Test to confirm that gdb is properly single stepping over the
+ displaced addpcis instruction. */
+
+.global main
+.type main,function
+# addpcis: the sum of NIA + ( D || 0x0000) is placed in RT.
+main:
+ subpcis 3,+0x100 # /* set r3 */
+ subpcis 4,+0x10 # /* set r4 */
+ subpcis 5,+0x1 # /* set r5 */
+ lnia 6 # /* set r6 */
+ addpcis 7,+0x1 # /* set r7 */
+ addpcis 8,+0x10 # /* set r8 */
+ addpcis 9,+0x100 # /* set r9 */
+ blr
diff --git a/gdb/testsuite/gdb.arch/powerpc-lnia.exp b/gdb/testsuite/gdb.arch/powerpc-lnia.exp
new file mode 100644
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-lnia.exp
@@ -0,0 +1,100 @@
+# Copyright 2021 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/>.
+
+# Test to see if gdb is properly single stepping over the
+# displaced lnia instruction. This test checks that a series
+# of lnia instructions are loading ascending values as expected.
+
+# lnia is an extended mnemonic for the addpcis instruction, which
+# stores the $NIA plus an immediate value into a register.
+#
+# lnia Rx == addpcis Rx,0 == lnia Rx
+# subcis Rx,value == addpcis Rx,-value
+
+if { ![istarget powerpc*-*] } {
+ verbose "Skipping powerpc lnia test."
+ return
+}
+
+set retval 0
+
+standard_testfile .s
+
+if { [prepare_for_testing "failed to prepare" $testfile "$srcfile" \
+ {debug quiet}] } {
+ return -1
+}
+
+if ![runto_main] then {
+ return
+}
+
+set before_pc 0
+set check_pc [get_hexadecimal_valueof "\$pc" "default0"]
+
+# set some breakpoints on the instructions below main().
+set bp1 *$check_pc+4
+set bp2 *$check_pc+12
+set bp3 *$check_pc+16
+gdb_breakpoint $bp1
+gdb_breakpoint $bp2
+gdb_breakpoint $bp3
+
+# single-step through the lnia instructions, and retrieve the
+# register values as we proceed.
+gdb_test "stepi" "" "set r3"
+set check_r3 [get_hexadecimal_valueof "\$r3" "default0"]
+gdb_test "stepi" "" "set r4"
+set check_r4 [get_hexadecimal_valueof "\$r4" "default0"]
+gdb_test "stepi" "" "set r5"
+set check_r5 [get_hexadecimal_valueof "\$r5" "default0"]
+gdb_test "stepi" "" "set r6"
+set check_r6 [get_hexadecimal_valueof "\$r6" "default0"]
+gdb_test "stepi" "" "set r7"
+set check_r7 [get_hexadecimal_valueof "\$r7" "default0"]
+gdb_test "stepi" "" "set r8"
+set check_r8 [get_hexadecimal_valueof "\$r8" "default0"]
+gdb_test "stepi" "" "set r9"
+set check_r9 [get_hexadecimal_valueof "\$r9" "default0"]
+
+# Ensure that our register values are as expected.
+# Specifically that the values loaded by the lnia instruction
+# reflect the value of the PC as if the instruction was
+# not displaced.
+if [expr $check_r3 + 4 != $check_r4] {
+ fail "unexpected value r3+4 != r4 , r3: $check_r3 r4: $check_r4 "
+}
+if [expr $check_r4 + 4 != $check_r5] {
+ fail "unexpected value r4+4 != r5 , r4: $check_r4 r5: $check_r5 "
+}
+if [expr $check_r5 + 4 != $check_r6] {
+ fail "unexpected value r5+4 != r6 , r5: $check_r5 r6: $check_r6 "
+}
+if [expr $check_r6 + 4 != $check_r7] {
+ fail "unexpected value r6+4 != r7 , r6: $check_r6 r7: $check_r7 "
+}
+if [expr $check_r7 + 4 != $check_r8] {
+ fail "unexpected value r7+4 != r8 , r7: $check_r7 r8: $check_r8 "
+}
+if [expr $check_r8 + 4 != $check_r9] {
+ fail "unexpected value r8+4 != r9 , r8: $check_r8 r9: $check_r9 "
+}
+
+gdb_test "info break"
+gdb_test "info register r3 r4 r5 r6 r7 r8 r9"
+gdb_test "disas main"
+
+# Let the inferior store all vector registers in a buffer, then dump
+# the buffer and check it.
diff --git a/gdb/testsuite/gdb.arch/powerpc-lnia.s b/gdb/testsuite/gdb.arch/powerpc-lnia.s
new file mode 100644
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-lnia.s
@@ -0,0 +1,32 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2021 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/>. */
+
+/* Test to confirm that gdb properly handles lnia instructions
+ that load the current PC into a target register when executed
+ from a displaced location. */
+
+.global main
+.type main,function
+main:
+ lnia 3 # /* set r3 */
+ lnia 4 # /* set r4 */
+ lnia 5 # /* set r5 */
+ lnia 6 # /* set r6 */
+ lnia 7 # /* set r7 */
+ lnia 8 # /* set r8 */
+ lnia 9 # /* set r9 */
+ blr
diff --git a/gdb/testsuite/gdb.arch/powerpc-plxv-nonrel.exp b/gdb/testsuite/gdb.arch/powerpc-plxv-nonrel.exp
new file mode 100644
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-plxv-nonrel.exp
@@ -0,0 +1,130 @@
+# Copyright 2021 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/>.
+
+# Test to see if gdb is properly single stepping over the
+# displaced plxv instruction.
+
+if { ![istarget powerpc*-*] } {
+ verbose "Skipping powerpc plxv test."
+ return
+}
+
+set retval 0
+
+standard_testfile .s
+
+if { [prepare_for_testing "failed to prepare" $testfile "$srcfile" \
+ {debug quiet}] } {
+ return -1
+}
+
+gdb_test "set radix 0b10000"
+gdb_test "set debug displaced"
+
+if ![runto_main] then {
+ return
+}
+
+gdb_test "set debug displaced on"
+
+# Proc to extract the uint128 hex value from the output of
+# a print vector statement.
+proc get_vector_hexadecimal_valueof { exp default {test ""} } {
+ set val "0x0000"
+ global gdb_prompt
+ if {$test == ""} {
+ set test "get vector_hexadecimal valueof \"${exp}\""
+ }
+ gdb_test_multiple "print $${exp}.uint128" $test {
+ -re -wrap "\\$\[0-9\]* = (0x\[0-9a-zA-Z\]+).*" {
+ set val $expect_out(1,string)
+ pass "$test"
+ }
+ -re -wrap ".*Illegal instruction.* $" {
+ fail "Illegal instruction on print."
+ set val 0xffff
+ }
+ }
+ return ${val}
+}
+
+# Proc to do a single-step, and ensure we gently handle
+# an illegal instruction situation.
+proc stepi_over_instruction { xyz } {
+ global gdb_prompt
+ gdb_test_multiple "stepi" "${xyz} " {
+ -re -wrap ".*Illegal instruction.*" {
+ fail "Illegal instruction on single step."
+ return
+ }
+ -re -wrap ".*" {
+ pass "stepi ${xyz}"
+ }
+ }
+}
+
+set check_pc [get_hexadecimal_valueof "\$pc" "default0"]
+
+# set some breakpoints on the instructions below main().
+gdb_test "disas /r main"
+set bp1 *$check_pc+4
+set bp2 *$check_pc+0d12
+set bp3 *$check_pc+0d20
+set bp4 *$check_pc+0d28
+gdb_breakpoint $bp1
+gdb_breakpoint $bp2
+gdb_breakpoint $bp3
+gdb_breakpoint $bp4
+
+# single-step through the plxv instructions, and retrieve the
+# register values as we proceed.
+
+stepi_over_instruction "stepi over NOP"
+stepi_over_instruction "stepi over lnia"
+stepi_over_instruction "stepi over addi"
+
+stepi_over_instruction "stepi over vs4 assignment"
+set check_vs4 [get_vector_hexadecimal_valueof "vs4" "default0"]
+
+stepi_over_instruction "stepi over vs5 assignment"
+set check_vs5 [get_vector_hexadecimal_valueof "vs5" "default0"]
+
+stepi_over_instruction "stepi over vs6 assignment"
+set check_vs6 [get_vector_hexadecimal_valueof "vs6" "default0"]
+
+stepi_over_instruction "stepi over vs7 assignment"
+set check_vs7 [get_vector_hexadecimal_valueof "vs7" "default0"]
+
+set vs4_expected 0xa5b5c5d5a4b4c4d4a3b3c3d3a2b2c2d2
+set vs5_expected 0xa7b7c7d7a6b6c6d6a5b5c5d5a4b4c4d4
+set vs6_expected 0xa9b9c9d9a8b8c8d8a7b7c7d7a6b6c6d6
+set vs7_expected 0xabbbcbdbaabacadaa9b9c9d9a8b8c8d8
+
+if [expr $check_vs4 != $vs4_expected] {
+ fail "unexpected value vs4; actual:$check_vs4 expected:$vs4_expected"
+}
+if [expr $check_vs5 != $vs5_expected ] {
+ fail "unexpected value vs5; actual:$check_vs5 expected:$vs5_expected"
+}
+if [expr $check_vs6 != $vs6_expected ] {
+ fail "unexpected value vs6; actual:$check_vs6 expected:$vs6_expected"
+}
+if [expr $check_vs7 != $vs7_expected ] {
+ fail "unexpected value vs7; actual:$check_vs7 expected:$vs7_expected"
+}
+
+gdb_test "info break"
+gdb_test "info register vs4 vs5 vs6 vs7 "
+gdb_test "disas main #2"
diff --git a/gdb/testsuite/gdb.arch/powerpc-plxv-nonrel.s b/gdb/testsuite/gdb.arch/powerpc-plxv-nonrel.s
new file mode 100644
--- /dev/null
+++ b/gdb/testsuite/gdb.arch/powerpc-plxv-nonrel.s
@@ -0,0 +1,44 @@
+# Copyright 2021 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/>.
+
+
+# test to verify that the prefixed instructions that
+# load/store non-relative values work OK.
+
+.global main
+.type main,function
+main:
+ nop
+ lnia 4
+ addi 4,4,40
+ plxv 4,4(4),0
+ plxv 5,12(4),0
+ plxv 6,20(4),0
+ plxv 7,28(4),0
+check_here:
+ blr
+mydata:
+ .long 0xa1b1c1d1 # <<-
+ .long 0xa2b2c2d2 # <<- loaded into vs4
+ .long 0xa3b3c3d3 # <<- loaded into vs4
+ .long 0xa4b4c4d4 # <<- loaded into vs4, vs5
+ .long 0xa5b5c5d5 # <<- loaded into vs4, vs5
+ .long 0xa6b6c6d6 # <<- loaded into vs5, vs6
+ .long 0xa7b7c7d7 # <<- loaded into vs5, vs6
+ .long 0xa8b8c8d8 # <<- loaded into vs6, vs7
+ .long 0xa9b9c9d9 # <<- loaded into vs6, vs7
+ .long 0xaabacada # <<- loaded into vs7
+ .long 0xabbbcbdb # <<- loaded into vs7
+ .long 0xacbcccdc # <<-