]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb/record: add support for AVX/AVX2 shuffle instructions
authorGuinevere Larsen <guinevere@redhat.com>
Mon, 9 Jun 2025 20:25:00 +0000 (17:25 -0300)
committerGuinevere Larsen <guinevere@redhat.com>
Fri, 11 Jul 2025 14:55:34 +0000 (11:55 -0300)
This commit adds support for the following instructions:
* VPSHUF[B|D|HW|LW]
* VSHUFP[S|D]

and the associated test.

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

index 4e442d28813b50155266ca2089f033a84fdc4c5c..e8e2d6e734b9048d2756bbf7125da4b2fc188e43 100644 (file)
@@ -5030,6 +5030,7 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
        break;
       }
 
+    case 0x00: /* VSHUFB.  */
     case 0x40: /* VPMULLD  */
     case 0x57: /* VXORP[S|D]  */
     case 0x58: /* VPBROADCASTD and VADD[P|S][S|D]  */
@@ -5038,8 +5039,10 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
     case 0x5d: /* VMIN[P|S][S|D]  */
     case 0x5e: /* VDIV[P|S][S|D]  */
     case 0x5f: /* VMAX[P|S][S|D]  */
+    case 0x70: /* VPSHUF[B|D|HW|LW].  */
     case 0x78: /* VPBROADCASTB  */
     case 0x79: /* VPBROADCASTW  */
+    case 0xc6: /* VSHUFP[S|D].  */
     case 0xd1: /* VPSRLW, dynamic shift.  */
     case 0xd2: /* VPSRLD, dynamic shift.  */
     case 0xd3: /* VPSRLQ, dynamic shift.  */
index 6ce8ff861bf7a6fb9dae00ea175c24e0e1764aee..d438a335e914258df498fbe2400e686a0b633a0a 100644 (file)
@@ -514,6 +514,35 @@ shift_test ()
   return 0; /* end shift_test  */
 }
 
+int
+shuffle_test ()
+{
+  /* start shuffle_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}
+     ymm2.v16_int15 = {17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}
+     ymm15.v2_int128 = {0x0, 0x0}
+     this way it's easy to confirm we're undoing things correctly.  */
+
+  asm volatile ("vpshufb %xmm1, %xmm2, %xmm0");
+  asm volatile ("vpshufb %ymm1, %ymm2, %ymm15");
+  asm volatile ("vpshufd $1, %ymm2, %ymm0");
+  asm volatile ("vpshufd $2, %xmm2, %xmm15");
+
+  asm volatile ("vpshufhw $3, %xmm2, %xmm0");
+  asm volatile ("vpshufhw $4, %ymm2, %ymm15");
+  asm volatile ("vpshuflw $5, %ymm2, %ymm0");
+  asm volatile ("vpshuflw $6, %xmm2, %xmm15");
+
+  asm volatile ("vshufps $1, %xmm1, %xmm2, %xmm0");
+  asm volatile ("vshufps $2, %ymm1, %ymm2, %ymm15");
+  asm volatile ("vshufpd $4, %ymm1, %ymm2, %ymm0");
+  asm volatile ("vshufpd $8, %xmm1, %xmm2, %xmm15");
+
+  return 0; /* end shuffle_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.  */
@@ -547,5 +576,6 @@ main ()
   vaddsubpd_test ();
   vaddsubps_test ();
   shift_test ();
+  shuffle_test ();
   return 0;    /* end of main */
 }
index ecd9fa6f4db1d1c9129346bd798bd9b69e748b2e..4bcafe7c331f8458790f92592408cb516524415b 100644 (file)
@@ -817,3 +817,57 @@ if {[record_full_function "shift"] == true} {
 }
 gdb_test "finish" "Run till exit from.*shift_test.*" \
     "leaving shift"
+
+# Preparation and testing shuffling instructions.
+gdb_test_no_output \
+    "set \$ymm0.v2_int128 = {0, 0}" "set ymm0 for shuffle"
+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 shuffle"
+gdb_test_no_output "set \$ymm2.v16_int16 = {17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}" \
+    "set ymm2 for shuffle"
+gdb_test_no_output "set \$ymm15.v2_int128 = {0,0}" "set ymm15 for shuffle"
+
+if {[record_full_function "shuffle"] == true} {
+    test_one_register "vshufpd" "ymm15" \
+       "0x20001000200010012001100160015, 0xa0009000a0009001a0019001e001d" \
+       "high register: "
+    test_one_register "vshufpd" "ymm0" \
+       "0x20001000200010012001100140013, 0x0" \
+       "low register: "
+    test_one_register "vshufps" "ymm15" \
+       "0x180017001600150011001100120013, 0x0" \
+       "high register: "
+    test_one_register "vshufps" "ymm0" \
+       "0x180017001600150011001100120012, 0x20001f001e001d00190019001a001a" \
+       "low register: "
+
+    test_one_register "vpshuflw" "ymm15" \
+       "0x150015001600150014001300120011, 0x1d001d001e001d001c001b001a0019" \
+       "high register: "
+    test_one_register "vpshuflw" "ymm0" \
+       "0x150015001500180014001300120011, 0x0" \
+       "low register: "
+    test_one_register "vpshufhw" "ymm15" \
+       "0x120011001200110012001100160015, 0x0" \
+       "high register: "
+    test_one_register "vpshufhw" "ymm0" \
+       "0x120011001200110012001100140013, 0x1a0019001a0019001a0019001c001b" \
+       "low register: "
+
+    test_one_register "vpshufd" "ymm15" \
+       "0x11151100111411001113110011121100, 0x1919190019201900191f1900191e1900" \
+       "high register: "
+    test_one_register "vpshufd" "ymm0" \
+       "0x11151100111411001113110011121100, 0x0" \
+       "low register: "
+    test_one_register "vpshufb" "ymm15" "0x0, 0x0" "high register: "
+    test_one_register "vpshufb" "ymm0" "0x0, 0x0" "low register: "
+
+    gdb_test "record stop" "Process record is stopped.*" \
+       "delete history for shuffle_test"
+} else {
+    untested "couldn't run shuffle tests"
+}
+gdb_test "finish" "Run till exit from.*shuffle_test.*" \
+    "leaving shuffle"