aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuinevere Larsen <guinevere@redhat.com>2024-11-12 16:37:32 -0300
committerGuinevere Larsen <guinevere@redhat.com>2024-11-22 17:40:25 -0300
commitf21055a4e9a2c3c2c7769e4ff7de246555dcd9be (patch)
tree3835ee8eb33130224bae8306a9ef9aa3998fcdaf
parentgdb/record: add support for vpxor instruction (diff)
downloadbinutils-gdb-f21055a4e9a2c3c2c7769e4ff7de246555dcd9be.tar.gz
binutils-gdb-f21055a4e9a2c3c2c7769e4ff7de246555dcd9be.tar.bz2
binutils-gdb-f21055a4e9a2c3c2c7769e4ff7de246555dcd9be.zip
gdb/record: Add support for all vpcmpeq instructions
This commit adds support to recording instructions of the form VPCMPEQ[B|W|D]. They are all encoded in the same way and only differentiated by the opcode, so they are all processed together. This commit also updates the test to (quite exhaustively) test the new instruction. Approved-By: Tom Tromey <tom@tromey.com>
-rw-r--r--gdb/i386-tdep.c11
-rw-r--r--gdb/testsuite/gdb.reverse/i386-avx-reverse.c32
-rw-r--r--gdb/testsuite/gdb.reverse/i386-avx-reverse.exp45
3 files changed, 88 insertions, 0 deletions
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 38b1e7a1f02..2a076700a67 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -4951,6 +4951,17 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
}
break;
+ case 0x74: /* VPCMPEQB */
+ case 0x75: /* VPCMPEQB */
+ case 0x76: /* VPCMPEQB */
+ {
+ i386_record_modrm (ir);
+ int reg_offset = ir->reg + vex_r * 8;
+ record_full_arch_list_add_reg (ir->regcache,
+ tdep->ymm0_regnum + reg_offset);
+ }
+ break;
+
case 0x78: /* VPBROADCASTB */
case 0x79: /* VPBROADCASTW */
case 0x58: /* VPBROADCASTD */
diff --git a/gdb/testsuite/gdb.reverse/i386-avx-reverse.c b/gdb/testsuite/gdb.reverse/i386-avx-reverse.c
index 9bdc365ed86..57b53d1390c 100644
--- a/gdb/testsuite/gdb.reverse/i386-avx-reverse.c
+++ b/gdb/testsuite/gdb.reverse/i386-avx-reverse.c
@@ -229,6 +229,37 @@ vpxor_test ()
return 0; /* end vpxor_test */
}
+int
+vpcmpeq_test ()
+{
+ /* start vpcmpeq_test. */
+ /* Using GDB, load these values onto registers for testing.
+ ymm0.v2_int128 = {0x0, 0x12345}
+ ymm1.v8_int32 = {0xcafe, 0xbeef, 0xff, 0x1234, 0x0, 0xff00, 0xff0000ff, 0xface0f0f}
+ ymm2.v8_int32 = {0xcafe0, 0xbeef, 0xff00, 0x12345678, 0x90abcdef, 0xffff00, 0xff, 0xf}
+ ymm15.v2_int128 = {0xcafeface, 0xcafeface}
+ this way it's easy to confirm we're undoing things correctly. */
+
+ /* Test all the vpcmpeq variants on a low register (number 0). */
+ asm volatile ("vpcmpeqb %xmm1, %xmm2, %xmm0");
+ asm volatile ("vpcmpeqw %xmm1, %xmm2, %xmm0");
+ asm volatile ("vpcmpeqd %xmm1, %xmm2, %xmm0");
+
+ asm volatile ("vpcmpeqb %ymm1, %ymm2, %ymm0");
+ asm volatile ("vpcmpeqw %ymm1, %ymm2, %ymm0");
+ asm volatile ("vpcmpeqd %ymm1, %ymm2, %ymm0");
+
+ /* Test all the vpcmpeq variants on a high register (number 15). */
+ asm volatile ("vpcmpeqb %xmm1, %xmm2, %xmm15");
+ asm volatile ("vpcmpeqw %xmm1, %xmm2, %xmm15");
+ asm volatile ("vpcmpeqd %xmm1, %xmm2, %xmm15");
+
+ asm volatile ("vpcmpeqb %ymm1, %ymm2, %ymm15");
+ asm volatile ("vpcmpeqw %ymm1, %ymm2, %ymm15");
+ asm volatile ("vpcmpeqd %ymm1, %ymm2, %ymm15");
+ return 0; /* end vpcmpeq_test */
+}
+
/* This include is used to allocate the dynamic buffer and have
the pointers aligned to a 32-bit boundary, so we can test instructions
that require aligned memory. */
@@ -255,5 +286,6 @@ main ()
vpbroadcast_test ();
vzeroupper_test ();
vpxor_test ();
+ vpcmpeq_test ();
return 0; /* end of main */
}
diff --git a/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp b/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp
index c4a54211592..b4f0e3b38b5 100644
--- a/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp
@@ -358,3 +358,48 @@ if {[record_full_function "vpxor"] == true} {
}
gdb_test "finish" "Run till exit from.*vpxor_test.*" \
"leaving vpxor"
+
+# Preparation and testing vpcmpeq instructions.
+gdb_test_no_output "set \$ymm0.v2_int128 = {0x12345, 0x12345}" \
+ "set ymm0 for vpcmpeq"
+gdb_test_no_output \
+ "set \$ymm1.v8_int32 = {0xcafe, 0xbeef, 0xff, 0x1234, 0x0, 0xff00, 0xff0000ff, 0xface0f0f}" \
+ "set ymm1 for vpcmpeq"
+gdb_test_no_output \
+ "set \$ymm2.v8_int32 = {0xcafe0, 0xbeef, 0xff00, 0x12345678, 0x90abcdef, 0xffff00, 0xff, 0xf}" \
+ "set ymm2 for vpcmpeq"
+gdb_test_no_output "set \$ymm15.v2_int128 = {0xcafeface, 0xcafeface}" \
+ "set ymm15 for vpcmpeq"
+
+if {[record_full_function "vpcmpeq"] == true} {
+ test_one_register "vpcmpeqd" "ymm15" \
+ "0xffff0000ffffffff00000000, 0xffff0000ffff00000000" "ymm: "
+ test_one_register "vpcmpeqw" "ymm15" \
+ "0xffff0000ffffffffff000000, 0xff00ffffffff00ffff00000000" "ymm: "
+ test_one_register "vpcmpeqb" "ymm15" \
+ "0xffffffff00000000, 0x0" "ymm: "
+ test_one_register "vpcmpeqd" "ymm15" \
+ "0xffff0000ffffffff00000000, 0x0" "xmm: "
+ test_one_register "vpcmpeqw" "ymm15" \
+ "0xffff0000ffffffffff000000, 0x0" "xmm: "
+ test_one_register "vpcmpeqb" "ymm15" "0xcafeface, 0xcafeface" "xmm: "
+
+ test_one_register "vpcmpeqd" "ymm0" \
+ "0xffff0000ffffffff00000000, 0xffff0000ffff00000000" "ymm: "
+ test_one_register "vpcmpeqw" "ymm0" \
+ "0xffff0000ffffffffff000000, 0xff00ffffffff00ffff00000000" "ymm: "
+ test_one_register "vpcmpeqb" "ymm0" \
+ "0xffffffff00000000, 0x0" "ymm: "
+ test_one_register "vpcmpeqd" "ymm0" \
+ "0xffff0000ffffffff00000000, 0x0" "xmm: "
+ test_one_register "vpcmpeqw" "ymm0" \
+ "0xffff0000ffffffffff000000, 0x0" "xmm: "
+ test_one_register "vpcmpeqb" "ymm0" "0x12345, 0x12345" "xmm: "
+
+ gdb_test "record stop" "Process record is stopped.*" \
+ "delete history for vpcmpeq_test"
+} else {
+ untested "couldn't run vpcmpeq tests"
+}
+gdb_test "finish" "Run till exit from.*vpcmpeq_test.*" \
+ "leaving vpcmpeq"