static int
i386_record_vex (struct i386_record_s *ir, uint8_t vex_w, uint8_t vex_r,
- int opcode, struct gdbarch *gdbarch)
+ struct gdbarch *gdbarch)
{
/* We need this to find YMM (and once AVX-512 is supported, ZMM) registers.
We should always save the largest available register, since an
SCOPE_EXIT { inferior_thread ()->set_executing (true); };
inferior_thread () -> set_executing (false);
+ uint8_t opcode;
+ if (record_read_memory (gdbarch, ir->addr, &opcode, 1))
+ return -1;
+ ir->addr++;
+
switch (opcode)
{
case 0x10: /* VMOVS[S|D] XMM, mem. */
}
break;
- case 0x78: /* VPBROADCASTB */
- case 0x79: /* VPBROADCASTW */
+ case 0x40: /* VPMULLD */
+ case 0x57: /* VXORP[S|D] */
case 0x58: /* VPBROADCASTD and VADD[P|S][S|D] */
case 0x59: /* VPBROADCASTQ and VMUL[P|S][S|D] */
case 0x5c: /* VSUB[P|S][S|D] */
case 0x5d: /* VMIN[P|S][S|D] */
case 0x5e: /* VDIV[P|S][S|D] */
case 0x5f: /* VMAX[P|S][S|D] */
+ case 0x78: /* VPBROADCASTB */
+ case 0x79: /* VPBROADCASTW */
+ case 0xd4: /* VPADDQ */
+ case 0xd5: /* VPMULLW */
+ case 0xdb: /* VPAND */
+ case 0xdf: /* VPANDN */
+ case 0xe5: /* VPMULHW */
+ case 0xe4: /* VPMULHUW */
+ case 0xf4: /* VPMULUDQ */
+ case 0xfc: /* VPADDB */
+ case 0xfd: /* VPADDW */
+ case 0xfe: /* VPADDD */
{
/* vpbroadcast and arithmetic operations are differentiated
by map_select, but it doesn't change the recording mechanics. */
"addr = %s\n",
paddress (gdbarch, ir.addr));
- /* prefixes */
- while (1)
+ /* Process the prefixes. This used to be an infinite loop, but since
+ a VEX prefix is always the last one before the opcode, according to
+ Intel's manual anyway, and some AVX opcodes may conflict with
+ prefixes, it's safe to leave the loop as soon as we see VEX. */
+ while (!vex_prefix)
{
if (record_read_memory (gdbarch, ir.addr, &opcode8, 1))
return -1;
{
/* If we found the VEX prefix, i386 will either record or warn that
the instruction isn't supported, so we can return the VEX result. */
- return i386_record_vex (&ir, rex_w, rex_r, opcode, gdbarch);
+ return i386_record_vex (&ir, rex_w, rex_r, gdbarch);
}
reswitch:
switch (opcode)
/* Using GDB, load these values onto registers for testing.
ymm0.v8_float = {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5}
ymm1.v8_float = {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5}
+ ymm2.v2_int128 = {0x0, 0x0}
ymm15.v2_int128 = {0x0, 0x0}
this way it's easy to confirm we're undoing things correctly. */
asm volatile ("vaddps %xmm0, %xmm1, %xmm15");
asm volatile ("vmaxss %xmm0, %xmm1, %xmm15");
asm volatile ("vmaxsd %xmm0, %xmm1, %xmm15");
+ /* Some sanity checks for other arithmetic instructions. */
+ asm volatile ("vpaddb %xmm0, %xmm1, %xmm2");
+ asm volatile ("vpaddw %xmm0, %xmm1, %xmm15");
+ asm volatile ("vpaddd %ymm0, %ymm1, %ymm2");
+ asm volatile ("vpaddq %ymm0, %ymm1, %ymm15");
+
+ asm volatile ("vpmullw %xmm0, %xmm1, %xmm2");
+ asm volatile ("vpmulld %xmm0, %xmm1, %xmm15");
+ asm volatile ("vpmulhw %ymm0, %ymm1, %ymm2");
+ asm volatile ("vpmulhuw %ymm0, %ymm1, %ymm15");
+ asm volatile ("vpmuludq %ymm0, %ymm1, %ymm15");
+
+ asm volatile ("vxorps %xmm0, %xmm1, %xmm2");
+ asm volatile ("vxorpd %ymm0, %ymm1, %ymm2");
+ asm volatile ("vpand %xmm0, %xmm1, %xmm15");
+ asm volatile ("vpandn %ymm0, %ymm1, %ymm15");
+
return 0; /* end arith_test */
}
"set \$ymm0.v8_float = {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5}"
gdb_test_no_output \
"set \$ymm1.v8_float = {0, 1, 2, 3, 4, 5, 6, 7}"
+gdb_test_no_output "set \$ymm2.v2_int128 = {0,0}"
gdb_test_no_output "set \$ymm15.v2_int128 = {0,0}"
if {[record_full_function "arith"] == true} {
+ test_one_register "vpandn" "ymm15" \
+ "0x40400000400000003f80000000000000, 0x0"
+ test_one_register "vpand" "ymm15" \
+ "0x10080000000000000000000000000000, 0x10649c00000000001044480000000000"
+ test_one_register "vxorpd" "ymm2" \
+ "0x20000000200000004000003f000000, 0x0"
+ test_one_register "vxorps" "ymm2" \
+ "0x10280000100800000fd0000000000000, 0x10740000106400001054000010440000"
+
+ test_one_register "vpmuludq" "ymm15" \
+ "0x10280000100800000fd0000000000000, 0x10740000106400001054000010440000"
+ test_one_register "vpmulhuw" "ymm15" \
+ "0x0, 0x0"
+ test_one_register "vpmulhw" "ymm2" \
+ "0x18000000000000002000000000000000, 0x0"
+ test_one_register "vpmulld" "ymm15" \
+ "0x80a00000802000007f4000003f000000, 0x81d00000819000008150000081100000"
+ test_one_register "vpmullw" "ymm2" \
+ "0x80a00000802000007f4000003f000000, 0x81d00000819000008150000081100000"
+
+ test_one_register "vpaddq" "ymm15" \
+ "0x80a00000802000007f4000003f000000, 0x0"
+ test_one_register "vpaddd" "ymm2" \
+ "0x80a00000802000007e4000003f000000, 0x0"
+ test_one_register "vpaddw" "ymm15" \
+ "0x40400000400000003fc000003f000000, 0x0"
+ test_one_register "vpaddb" "ymm2" \
+ "0x0, 0x0"
+
test_one_register "vmaxsd" "ymm15" \
"0x40400000400000003f8000003f000000, 0x0" "ymm operation: "
test_one_register "vmaxss" "ymm15" \