From b97691b926c1616c674e9e6a9f15e24bfb82eaea Mon Sep 17 00:00:00 2001 From: Guinevere Larsen Date: Tue, 17 Jun 2025 09:35:03 -0300 Subject: [PATCH] gdb/record: Add support for more vmov-style instructions 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 | 35 ++++++++++++------- gdb/testsuite/gdb.reverse/i386-avx-reverse.c | 29 +++++++++++++++ .../gdb.reverse/i386-avx-reverse.exp | 35 ++++++++++++++++--- 3 files changed, 82 insertions(+), 17 deletions(-) diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 103bec4054e..b50a7c34ce6 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -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); diff --git a/gdb/testsuite/gdb.reverse/i386-avx-reverse.c b/gdb/testsuite/gdb.reverse/i386-avx-reverse.c index d514bf0f222..a3d64272f24 100644 --- a/gdb/testsuite/gdb.reverse/i386-avx-reverse.c +++ b/gdb/testsuite/gdb.reverse/i386-avx-reverse.c @@ -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 (); diff --git a/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp b/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp index 601ed4b0f2a..7e75542720c 100644 --- a/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp +++ b/gdb/testsuite/gdb.reverse/i386-avx-reverse.exp @@ -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 " 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 " test_one_general_register "vpextrq" "rax" "0x80007" test_one_memory "vpextrd" "global_buf1" \ - "\\\{0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18" + "\\\{0x3, 0x0 " test_one_general_register "vpextrd" "rax" "0x0" test_one_memory "vpextrb" "global_buf1" \ - "\\\{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x18" + "\\\{0x0 " test_one_general_register "vpextrb" "rax" "0xcafe" test_one_general_register "vextractps" "eax" "0x0" -- 2.47.2