aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuinevere Larsen <guinevere@redhat.com>2025-06-09 16:04:48 -0300
committerGuinevere Larsen <guinevere@redhat.com>2025-07-11 11:55:34 -0300
commitcdc328ea65b499e1e0cbc142e06645801a42c5f3 (patch)
tree58ae08c4b345c99bd5030d9da38967207fdf3758
parent77a7df4756cd4b07bc1c3efbae774498fcebc77e (diff)
downloadbinutils-cdc328ea65b499e1e0cbc142e06645801a42c5f3.zip
binutils-cdc328ea65b499e1e0cbc142e06645801a42c5f3.tar.gz
binutils-cdc328ea65b499e1e0cbc142e06645801a42c5f3.tar.bz2
gdb/record: Add support for AVX/AVX2 shift instructions
This commit adds record-full support to the following instructions: * VPSLL[W|D|Q|DQ] * VPSRL[W|D|Q|DQ] * VPSRA[W|D] With both dynamic and constant shifts, and the associated tests. Notably, vpsraq is not available for AVX or AVX2 instruction sets, only AVX512. vpsradq does not seem to be available with any instruction set.
-rw-r--r--gdb/i386-tdep.c17
-rw-r--r--gdb/testsuite/gdb.reverse/i386-avx-reverse.c47
-rw-r--r--gdb/testsuite/gdb.reverse/i386-avx-reverse.exp91
3 files changed, 155 insertions, 0 deletions
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 67feb81..4e442d2 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -5021,6 +5021,15 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
}
break;
+ case 0x71: /* VPS[LL|RA|RL]W with constant shift. */
+ case 0x72: /* VPS[LL|RA|RL]D with constant shift. */
+ case 0x73: /* VPS[LL|RL][Q|DQ] with constant shift. */
+ {
+ record_full_arch_list_add_reg (ir->regcache,
+ tdep->ymm0_regnum + ir->vvvv);
+ break;
+ }
+
case 0x40: /* VPMULLD */
case 0x57: /* VXORP[S|D] */
case 0x58: /* VPBROADCASTD and VADD[P|S][S|D] */
@@ -5031,12 +5040,20 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
case 0x5f: /* VMAX[P|S][S|D] */
case 0x78: /* VPBROADCASTB */
case 0x79: /* VPBROADCASTW */
+ case 0xd1: /* VPSRLW, dynamic shift. */
+ case 0xd2: /* VPSRLD, dynamic shift. */
+ case 0xd3: /* VPSRLQ, dynamic shift. */
case 0xd4: /* VPADDQ */
case 0xd5: /* VPMULLW */
case 0xdb: /* VPAND */
case 0xdf: /* VPANDN */
+ case 0xe1: /* VPSRAW, dynamic shift. */
+ case 0xe2: /* VPSRAD, dynamic shift. */
case 0xe5: /* VPMULHW */
case 0xe4: /* VPMULHUW */
+ case 0xf1: /* VPSLLW, dynamic shift. */
+ case 0xf2: /* VPSLLD, dynamic shift. */
+ case 0xf3: /* VPSLLQ, dynamic shift. */
case 0xf4: /* VPMULUDQ */
case 0xfc: /* VPADDB */
case 0xfd: /* VPADDW */
diff --git a/gdb/testsuite/gdb.reverse/i386-avx-reverse.c b/gdb/testsuite/gdb.reverse/i386-avx-reverse.c
index 3ebb4dd..6ce8ff8 100644
--- a/gdb/testsuite/gdb.reverse/i386-avx-reverse.c
+++ b/gdb/testsuite/gdb.reverse/i386-avx-reverse.c
@@ -468,6 +468,52 @@ vaddsubps_test ()
}
+/* Test record shifting instructions. */
+int
+shift_test ()
+{
+ /* start shift_test. */
+ /* Using GDB, load these values onto registers for testing.
+ ymm0.v2_int128 = {0, 0}
+ ymm1.v16_int16 = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}
+ xmm2.uint128 = 1
+ ymm15.v2_int128 = {0x0, 0x0}
+ this way it's easy to confirm we're undoing things correctly. */
+
+ asm volatile ("vpsllw $1, %xmm1, %xmm0");
+ asm volatile ("vpsllw %xmm2, %ymm1, %ymm0");
+ asm volatile ("vpslld $3, %ymm1, %ymm15");
+ asm volatile ("vpslld %xmm2, %xmm1, %xmm15");
+ asm volatile ("vpsllq $5, %xmm1, %xmm15");
+ asm volatile ("vpsllq %xmm2, %ymm1, %ymm15");
+
+ asm volatile ("vpsraw $1, %xmm1, %xmm0");
+ asm volatile ("vpsraw %xmm2, %ymm1, %ymm0");
+ asm volatile ("vpsrad $3, %ymm1, %ymm15");
+ asm volatile ("vpsrad %xmm2, %xmm1, %xmm15");
+
+ asm volatile ("vpsrlw $1, %xmm1, %xmm0");
+ asm volatile ("vpsrlw %xmm2, %ymm1, %ymm0");
+ asm volatile ("vpsrld $3, %ymm1, %ymm15");
+ asm volatile ("vpsrld %xmm2, %xmm1, %xmm15");
+ asm volatile ("vpsrlq $5, %xmm1, %xmm15");
+ asm volatile ("vpsrlq %xmm2, %ymm1, %ymm15");
+
+ /* The dq version is treated separately in the manual, so
+ we test it separately just to be sure. */
+ asm volatile ("vpslldq $1, %xmm1, %xmm0");
+ asm volatile ("vpslldq $2, %ymm1, %ymm0");
+ asm volatile ("vpslldq $3, %xmm1, %xmm15");
+ asm volatile ("vpslldq $4, %ymm1, %ymm15");
+
+ asm volatile ("vpsrldq $1, %xmm1, %xmm0");
+ asm volatile ("vpsrldq $2, %ymm1, %ymm0");
+ asm volatile ("vpsrldq $3, %xmm1, %xmm15");
+ asm volatile ("vpsrldq $4, %ymm1, %ymm15");
+
+ return 0; /* end shift_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. */
@@ -500,5 +546,6 @@ main ()
arith_test ();
vaddsubpd_test ();
vaddsubps_test ();
+ shift_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 c373375..ecd9fa6 100644
--- a/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp
+++ b/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp
@@ -726,3 +726,94 @@ if {[record_full_function "vaddsubps"] == true} {
}
gdb_test "finish" "Run till exit from.*vaddsubps_test.*" \
"leaving vaddsubps"
+
+# Preparation and testing shifting instructions.
+gdb_test_no_output \
+ "set \$ymm0.v2_int128 = {0, 0}" "set ymm0 for shift"
+gdb_test_no_output \
+ "set \$ymm1.v16_int16 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}" \
+ "set ymm1 for shift"
+gdb_test_no_output "set \$xmm2.uint128 = 1" "set ymm2 for shift"
+gdb_test_no_output "set \$ymm15.v2_int128 = {0,0}" "set ymm15 for shift"
+
+if {[record_full_function "shift"] == true} {
+ test_one_register "vpsrldq" "ymm15" \
+ "0x80007000600050004000300, 0x0" \
+ "High ymm register: "
+ test_one_register "vpsrldq" "ymm15" \
+ "0x60005000400030002000100000000, 0xe000d000c000b000a000900000000" \
+ "High xmm register: "
+ test_one_register "vpsrldq" "ymm0" \
+ "0x800070006000500040003000200, 0x0" \
+ "Low ymm register: "
+ test_one_register "vpsrldq" "ymm0" \
+ "0x70006000500040003000200010000, 0xf000e000d000c000b000a00090000" \
+ "Low xmm register: "
+
+ test_one_register "vpslldq" "ymm15" \
+ "0x7000600050004000300020001000000, 0x0" \
+ "High ymm register: "
+ test_one_register "vpslldq" "ymm15" \
+ "0x40003800300020002000180010000, 0x80007800700060006000580050004" \
+ "High xmm register: "
+ test_one_register "vpslldq" "ymm0" \
+ "0x8000700060005000400030002000100, 0x0" \
+ "Low ymm register: "
+ test_one_register "vpslldq" "ymm0" \
+ "0x40003000300020002000100010000, 0x80007000700060006000500050004" \
+ "Low xmm register: "
+
+ test_one_register "vpsrlq" "ymm15" \
+ "0x4000380030000000200018001000, 0x0" \
+ "from register: "
+ test_one_register "vpsrlq" "ymm15" \
+ "0x40003000300020002000100010000, 0x0" \
+ "from constant: "
+ test_one_register "vpsrld" "ymm15" \
+ "0x100000000c0000000800000004000, 0x200010001c0010001800100014001" \
+ "from register: "
+ test_one_register "vpsrld" "ymm15" \
+ "0x40003000300020002000100010000, 0x0" \
+ "from constant: "
+ test_one_register "vpsrlw" "ymm0" \
+ "0x40003000300020002000100010000, 0x0" \
+ "from register: "
+ test_one_register "vpsrlw" "ymm0" \
+ "0x40003000300020002000100010000, 0x80007000700060006000500050004" \
+ "from constant: "
+
+ test_one_register "vpsrad" "ymm15" \
+ "0x100000000c0000000800000004000, 0x200010001c0010001800100014001" \
+ "from register: "
+ test_one_register "vpsrad" "ymm15" \
+ "0x10000e000c000a0008000600040002, 0x20001e001c001a0018001600140012" \
+ "from constant: "
+ test_one_register "vpsraw" "ymm0" \
+ "0x40003000300020002000100010000, 0x0" \
+ "from register: "
+ test_one_register "vpsraw" "ymm0" \
+ "0x10000e000c000a0008000600040002, 0x20001e001c001a0018001600140012" \
+ "from constant: "
+
+ test_one_register "vpsllq" "ymm15" \
+ "0x10000e000c000a00080006000400020, 0x0" \
+ "from register: "
+ test_one_register "vpsllq" "ymm15" \
+ "0x10000e000c000a0008000600040002, 0x0" \
+ "from constant: "
+ test_one_register "vpslld" "ymm15" \
+ "0x400038003000280020001800100008, 0x800078007000680060005800500048" \
+ "from register: "
+ test_one_register "vpslld" "ymm15" "0x0, 0x0" "from constant: "
+ test_one_register "vpsllw" "ymm0" \
+ "0x10000e000c000a0008000600040002, 0x0" \
+ "from register: "
+ test_one_register "vpsllw" "ymm0" "0x0, 0x0" "from constant: "
+
+ gdb_test "record stop" "Process record is stopped.*" \
+ "delete history for shift_test"
+} else {
+ untested "couldn't run shift tests"
+}
+gdb_test "finish" "Run till exit from.*shift_test.*" \
+ "leaving shift"