}
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);
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)
+ 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. */
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. */
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);
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 ()
{
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 */
asm volatile ("vmovq %0, %%xmm15": : "m" (global_buf1));
vmov_test ();
+ reset_buffers ();
vpunpck_test ();
vpbroadcast_test ();
vzeroupper_test ();
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
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" \
"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"