]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb/record: Add support for AVX/AVX2 shift instructions
authorGuinevere Larsen <guinevere@redhat.com>
Mon, 9 Jun 2025 19:04:48 +0000 (16:04 -0300)
committerGuinevere Larsen <guinevere@redhat.com>
Fri, 11 Jul 2025 14:55:34 +0000 (11:55 -0300)
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.

gdb/i386-tdep.c
gdb/testsuite/gdb.reverse/i386-avx-reverse.c
gdb/testsuite/gdb.reverse/i386-avx-reverse.exp

index 67feb81b0927ceaf242568366aa72409676f476a..4e442d28813b50155266ca2089f033a84fdc4c5c 100644 (file)
@@ -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  */
index 3ebb4ddc48d14005bc81def49443fbc28df18e0b..6ce8ff861bf7a6fb9dae00ea175c24e0e1764aee 100644 (file)
@@ -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 */
 }
index c37337574da71f1784bd6e39a679d47df4fe2475..ecd9fa6f4db1d1c9129346bd798bd9b69e748b2e 100644 (file)
@@ -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"