]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gdb/record: Add support for more vmov-style instructions
authorGuinevere Larsen <guinevere@redhat.com>
Tue, 17 Jun 2025 12:35:03 +0000 (09:35 -0300)
committerGuinevere Larsen <guinevere@redhat.com>
Fri, 11 Jul 2025 14:55:34 +0000 (11:55 -0300)
This commit adds support for a few more vmov instructions:
* VMOV[LH|HL]PS
* VMOVLPD
* VMOVHP[S|D]
* VMOVDDUP

And associated tests. The testsuite had some minor re-working, adding a
function to zero buffers, to make later tests less fragile.

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

index 103bec4054ec78ee0a36c1bdc40f842af35c4f7d..b50a7c34ce6b6674cfc97666b047452ac8e4efba 100644 (file)
@@ -4988,13 +4988,6 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
        }
       break;
 
-    case 0x17: /* VEXTRACTPS.  */
-      i386_record_modrm (ir);
-      record_full_arch_list_add_reg (ir->regcache,
-                                    ir->regmap[X86_RECORD_REAX_REGNUM
-                                               + ir->rm]);
-      break;
-
     case 0x19: /* VBROADCASTSD and VEXTRACTF128.  */
     case 0x39: /* VEXTRACTI128.  */
       i386_record_modrm (ir);
@@ -5035,13 +5028,13 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
 
     case 0x14: /* VPEXTRB and VUNPCKL[PS|PD].  */
     case 0x15: /* VPEXTRW (to memory) and VUNPCKH [PS|PD].  */
-    case 0x16: /* VPEXTR[D|Q] and VPERMPS.  */
+    case 0x16: /* VPEXTR[D|Q], VPERMPS, VMOVLHPS and VMOVHP[S|D] to reg.  */
       {
        i386_record_modrm (ir);
        /* All vpextr instructions in this case use map_select == 3,
-          while vpermps and vunpck have map_select equal to 2 and 1,
-          respectively.  The opcode 0xc5 is for vpextr, but uses
-          map_select == 1, but due to other inconsistencies with
+          while vpermps has map_select == 2 and the other instructions
+          have map_select == 1.  The opcode 0xc5 is for vpextr, but also
+          uses map_select == 1, but due to other inconsistencies with
           the other vpextr instructions, it is in a separate case to
           avoid making this even more of a mess.  */
        if (ir->map_select == 3)
@@ -5116,6 +5109,20 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
                                                + ir->reg]);
       break;
 
+    case 0x17: /* VEXTRACTPS and VMOVHP[S|D] to memory.  */
+    case 0x13: /* VMOVLPD to memory.  */
+      i386_record_modrm (ir);
+      if (ir->map_select == 1) /* This is the VMOV family.  */
+       {
+         ir->ot = 3;
+         i386_record_lea_modrm (ir);
+       }
+      else
+       record_full_arch_list_add_reg (ir->regcache,
+                                      ir->regmap[X86_RECORD_REAX_REGNUM
+                                                 + ir->rm]);
+      break;
+
     case 0x00: /* VSHUFB and VPERMQ.  */
     case 0x01: /* VPERMPD.  */
     case 0x02: /* VPBLENDD.  */
@@ -5125,6 +5132,7 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
     case 0x0c: /* VPERMILPS with register and VBLENDPS.  */
     case 0x0d: /* VPERMILPD with register and VBLENDPD.  */
     case 0x0e: /* VPBLENDW.  */
+    case 0x12: /* VMOVDDUP, VMOVHLPS and VMOVLPD to register.  */
     case 0x1a: /* VBROADCASTF128.  */
     case 0x2a: /* VCVTSI2SS.  */
     case 0x2b: /* VPACKUSDW.  */
@@ -5171,8 +5179,9 @@ i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
     case 0xfd: /* VPADDW  */
     case 0xfe: /* VPADDD  */
       {
-       /* vpbroadcast and arithmetic operations are differentiated
-          by map_select, but it doesn't change the recording mechanics.  */
+       /* This set of instructions all share the same exact way to encode
+          the destination register, so there's no reason to try and
+          differentiate them.  */
        i386_record_modrm (ir);
        int reg_offset = ir->reg + vex_r * 8;
        gdb_assert (tdep->num_ymm_regs > reg_offset);
index d514bf0f222894670d034f6929beb8311bd57142..a3d64272f2459c895227f3ba073ded80a44550de 100644 (file)
@@ -30,6 +30,18 @@ char global_buf1[] = {0, 0, 0, 0, 0, 0, 0, 0,
 char *dyn_buf0;
 char *dyn_buf1;
 
+  /* Zero memory regions again, so that future tests can update them
+     without worry.  */
+void
+reset_buffers ()
+{
+  for (int i = 0; i < 32; i++)
+    {
+      global_buf1[i] = 0;
+      dyn_buf1[i] = 0;
+    }
+}
+
 int
 vmov_test ()
 {
@@ -168,6 +180,22 @@ vmov_test ()
   asm volatile ("vmovapd %%xmm0, %0"  : : "m"(*dyn_buf1));
   asm volatile ("vmovaps %%ymm15, %0" : : "m"(*dyn_buf1));
 
+  /* Testing vmov[hl|lh]ps and vmov[h|l]pd.  */
+  asm volatile ("vmovhlps %xmm1, %xmm8, %xmm0");
+  asm volatile ("vmovhlps %xmm1, %xmm2, %xmm15");
+  asm volatile ("vmovlhps %xmm1, %xmm8, %xmm0");
+  asm volatile ("vmovlhps %xmm1, %xmm2, %xmm15");
+
+  asm volatile ("vmovhps %0, %%xmm1, %%xmm0" : : "m"(buf0));
+  asm volatile ("vmovhps %%xmm0, %0" : "=m" (buf1));
+  asm volatile ("vmovhpd %0, %%xmm1, %%xmm15" : : "m"(global_buf0));
+  asm volatile ("vmovhpd %%xmm15, %0" : "=m" (global_buf1));
+  asm volatile ("vmovlpd %0, %%xmm1, %%xmm15" : : "m"(*dyn_buf0));
+  asm volatile ("vmovlpd %%xmm15, %0" : "=m" (*dyn_buf1));
+
+  asm volatile ("vmovddup %xmm1, %xmm15");
+  asm volatile ("vmovddup %ymm2, %ymm0");
+
   /* We have a return statement to deal with
      epilogue in different compilers.  */
   return 0; /* end vmov_test */
@@ -760,6 +788,7 @@ main ()
   asm volatile ("vmovq %0, %%xmm15": : "m" (global_buf1));
 
   vmov_test ();
+  reset_buffers ();
   vpunpck_test ();
   vpbroadcast_test ();
   vzeroupper_test ();
index 601ed4b0f2a56cac8d1f848845809e67f262e512..7e75542720cc6b1a8b303fd88d84a80e3cac4fba 100644 (file)
@@ -149,6 +149,33 @@ global decimal
 if {[record_full_function "vmov"] == true} {
     # Now execute backwards, checking all instructions.
 
+    test_one_register "vmovddup" "ymm0" \
+       "0x3736353433323130c004000000000000, 0x0"
+    test_one_register "vmovddup" "ymm15" \
+       "0x2726252423222120, 0x0"
+    test_one_memory "vmovlpd" "dyn_buf1" \
+       "\\\{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x28" \
+       true
+    test_one_register "vmovlpd" "ymm15" \
+       "0x1716151413121110c004000000000000, 0x0"
+    test_one_memory "vmovhpd" "global_buf1" \
+       "\\\{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18"
+    test_one_register "vmovhpd" "ymm15" \
+       "0xc004000000000000c004000000000000, 0x0"
+    test_one_memory "vmovhps" "buf1" \
+       "\\\{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x38"
+    test_one_register "vmovhps" "ymm0" \
+       "0xc004000000000000c004000000000000, 0x0"
+
+    test_one_register "vmovlhps" "ymm15" \
+       "0x0, 0x0"
+    test_one_register "vmovlhps" "ymm0" \
+       "0x0, 0x0"
+    test_one_register "vmovhlps" "ymm15" \
+       "0x2f2e2d2c2b2a29280000000000000000, 0x2f2e2d2c2b2a29282726252423222120"
+    test_one_register "vmovhlps" "ymm0" \
+       "0x2f2e2d2c2b2a29282726252423222120, 0x0"
+
     # Explicitly test for the start of the array, since the value repeats.
     test_one_memory "vmovaps" "dyn_buf1" \
        "\\\{0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28" true
@@ -977,7 +1004,7 @@ gdb_test_no_output "set \$rax = 0" "set eax for extract_insert"
 
 if {[record_full_function "extract_insert"] == true} {
     test_one_memory "vpextrw" "global_buf1" \
-       "\\\{0x1, 0x0, 0x2, 0x0, 0x3, 0x0, 0x4, 0x0, 0x18"
+       "\\\{0x1, 0x0, 0x2, 0x0, 0x3, 0x0, 0x4, 0x0 <repeats 25 times>"
     test_one_general_register "vpextrw" "rax" "0x8000700060005"
 
     test_one_register "vpinsrq" "ymm15" \
@@ -990,13 +1017,13 @@ if {[record_full_function "extract_insert"] == true} {
        "0x80007000600050000cafe00020001, 0x0"
 
     test_one_memory "vpextrq" "global_buf1" \
-       "\\\{0x5, 0x0, 0x6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18"
+       "\\\{0x5, 0x0, 0x6, 0x0 <repeats 29 times>"
     test_one_general_register "vpextrq" "rax" "0x80007"
     test_one_memory "vpextrd" "global_buf1" \
-       "\\\{0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18"
+       "\\\{0x3, 0x0 <repeats 31 times>"
     test_one_general_register "vpextrd" "rax" "0x0"
     test_one_memory "vpextrb" "global_buf1" \
-       "\\\{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18"
+       "\\\{0x0 <repeats 32 times>"
     test_one_general_register "vpextrb" "rax" "0xcafe"
 
     test_one_general_register "vextractps" "eax" "0x0"