LibX86: Support SSE2 :^)

This allows disassembly of binaries with SSE2 instructions in them.
SSE2 also extends all MMX instructions without affecting the mnemonic,
therefore these are just directed to the same function for now.
The UserspaceEmulator does not know this as of
this commit.
This commit is contained in:
Hendiadyoin1 2022-04-06 15:51:48 +02:00 committed by Andreas Kling
parent 5987f0a8f5
commit 3e3b677852
5 changed files with 414 additions and 35 deletions

View file

@ -2981,6 +2981,80 @@ VPU_INSTRUCTION(PSADBB_mm1_mm2m64);
VPU_INSTRUCTION(PSADBB_xmm1_xmm2m128);
VPU_INSTRUCTION(MASKMOVQ_mm1_mm2m64);
void SoftCPU::MOVUPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVSD_xmm1_xmm2m32(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVUPD_xmm1m128_xmm2(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVSD_xmm1m32_xmm2(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVLPD_xmm1_m64(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVLPD_m64_xmm2(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::UNPCKLPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::UNPCKHPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVHPD_xmm1_xmm2m64(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVAPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVAPD_xmm1m128_xmm2(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTPI2PD_xmm1_mm2m64(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTSI2SD_xmm1_rm32(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTTPD2PI_mm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTTSS2SI_r32_xmm2m64(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTPD2PI_xmm1_mm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTSD2SI_xmm1_rm64(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::UCOMISD_xmm1_xmm2m64(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::COMISD_xmm1_xmm2m64(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVMSKPD_reg_xmm(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::SQRTPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::SQRTSD_xmm1_xmm2m32(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::ANDPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::ANDNPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::ORPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::XORPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::ADDPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::ADDSD_xmm1_xmm2m32(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MULPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MULSD_xmm1_xmm2m32(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTPS2PD_xmm1_xmm2m64(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTPD2PS_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTSS2SD_xmm1_xmm2m32(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTSD2SS_xmm1_xmm2m64(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTDQ2PS_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTPS2DQ_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTTPS2DQ_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::SUBPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); };
void SoftCPU::SUBSD_xmm1_xmm2m32(X86::Instruction const&) { TODO_INSN(); };
void SoftCPU::MINPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MINSD_xmm1_xmm2m32(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::DIVPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::DIVSD_xmm1_xmm2m32(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MAXPD_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MAXSD_xmm1_xmm2m32(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::PUNPCKLQDQ_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::PUNPCKHQDQ_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVDQA_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVDQU_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::PSHUFD_xmm1_xmm2m128_imm8(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::PSHUFHW_xmm1_xmm2m128_imm8(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::PSHUFLW_xmm1_xmm2m128_imm8(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::PSRLQ_xmm1_imm8(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::PSRLDQ_xmm1_imm8(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::PSLLQ_xmm1_imm8(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::PSLLDQ_xmm1_imm8(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVD_rm32_xmm2(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVQ_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVDQA_xmm1m128_xmm2(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVDQU_xmm1m128_xmm2(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CMPPD_xmm1_xmm2m128_imm8(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CMPSD_xmm1_xmm2m32_imm8(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::SHUFPD_xmm1_xmm2m128_imm8(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::PADDQ_mm1_mm2m64(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVQ_xmm1m128_xmm2(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVQ2DQ_xmm_mm(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::MOVDQ2Q_mm_xmm(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTTPD2DQ_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTPD2DQ_xmm1_xmm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::CVTDQ2PD_xmm1_xmm2m64(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::PMULUDQ_mm1_mm2m64(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::PMULUDQ_mm1_mm2m128(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::PSUBQ_mm1_mm2m64(X86::Instruction const&) { TODO_INSN(); }
void SoftCPU::wrap_0xC0(const X86::Instruction&) { TODO_INSN(); }
void SoftCPU::wrap_0xC1_16(const X86::Instruction&) { TODO_INSN(); }
void SoftCPU::wrap_0xC1_32(const X86::Instruction&) { TODO_INSN(); }

View file

@ -1188,6 +1188,80 @@ private:
virtual void PSADBB_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void MASKMOVQ_mm1_mm2m64(X86::Instruction const&) override;
virtual void MOVUPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void MOVSD_xmm1_xmm2m32(X86::Instruction const&) override;
virtual void MOVUPD_xmm1m128_xmm2(X86::Instruction const&) override;
virtual void MOVSD_xmm1m32_xmm2(X86::Instruction const&) override;
virtual void MOVLPD_xmm1_m64(X86::Instruction const&) override;
virtual void MOVLPD_m64_xmm2(X86::Instruction const&) override;
virtual void UNPCKLPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void UNPCKHPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void MOVHPD_xmm1_xmm2m64(X86::Instruction const&) override;
virtual void MOVAPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void MOVAPD_xmm1m128_xmm2(X86::Instruction const&) override;
virtual void CVTPI2PD_xmm1_mm2m64(X86::Instruction const&) override;
virtual void CVTSI2SD_xmm1_rm32(X86::Instruction const&) override;
virtual void CVTTPD2PI_mm1_xmm2m128(X86::Instruction const&) override;
virtual void CVTTSS2SI_r32_xmm2m64(X86::Instruction const&) override;
virtual void CVTPD2PI_xmm1_mm2m128(X86::Instruction const&) override;
virtual void CVTSD2SI_xmm1_rm64(X86::Instruction const&) override;
virtual void UCOMISD_xmm1_xmm2m64(X86::Instruction const&) override;
virtual void COMISD_xmm1_xmm2m64(X86::Instruction const&) override;
virtual void MOVMSKPD_reg_xmm(X86::Instruction const&) override;
virtual void SQRTPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void SQRTSD_xmm1_xmm2m32(X86::Instruction const&) override;
virtual void ANDPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void ANDNPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void ORPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void XORPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void ADDPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void ADDSD_xmm1_xmm2m32(X86::Instruction const&) override;
virtual void MULPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void MULSD_xmm1_xmm2m32(X86::Instruction const&) override;
virtual void CVTPS2PD_xmm1_xmm2m64(X86::Instruction const&) override;
virtual void CVTPD2PS_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void CVTSS2SD_xmm1_xmm2m32(X86::Instruction const&) override;
virtual void CVTSD2SS_xmm1_xmm2m64(X86::Instruction const&) override;
virtual void CVTDQ2PS_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void CVTPS2DQ_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void CVTTPS2DQ_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void SUBPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void SUBSD_xmm1_xmm2m32(X86::Instruction const&) override;
virtual void MINPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void MINSD_xmm1_xmm2m32(X86::Instruction const&) override;
virtual void DIVPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void DIVSD_xmm1_xmm2m32(X86::Instruction const&) override;
virtual void MAXPD_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void MAXSD_xmm1_xmm2m32(X86::Instruction const&) override;
virtual void PUNPCKLQDQ_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void PUNPCKHQDQ_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void MOVDQA_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void MOVDQU_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void PSHUFD_xmm1_xmm2m128_imm8(X86::Instruction const&) override;
virtual void PSHUFHW_xmm1_xmm2m128_imm8(X86::Instruction const&) override;
virtual void PSHUFLW_xmm1_xmm2m128_imm8(X86::Instruction const&) override;
virtual void PSRLQ_xmm1_imm8(X86::Instruction const&) override;
virtual void PSRLDQ_xmm1_imm8(X86::Instruction const&) override;
virtual void PSLLQ_xmm1_imm8(X86::Instruction const&) override;
virtual void PSLLDQ_xmm1_imm8(X86::Instruction const&) override;
virtual void MOVD_rm32_xmm2(X86::Instruction const&) override;
virtual void MOVQ_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void MOVDQA_xmm1m128_xmm2(X86::Instruction const&) override;
virtual void MOVDQU_xmm1m128_xmm2(X86::Instruction const&) override;
virtual void CMPPD_xmm1_xmm2m128_imm8(X86::Instruction const&) override;
virtual void CMPSD_xmm1_xmm2m32_imm8(X86::Instruction const&) override;
virtual void SHUFPD_xmm1_xmm2m128_imm8(X86::Instruction const&) override;
virtual void PADDQ_mm1_mm2m64(X86::Instruction const&) override;
virtual void MOVQ_xmm1m128_xmm2(X86::Instruction const&) override;
virtual void MOVQ2DQ_xmm_mm(X86::Instruction const&) override;
virtual void MOVDQ2Q_mm_xmm(X86::Instruction const&) override;
virtual void CVTTPD2DQ_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void CVTPD2DQ_xmm1_xmm2m128(X86::Instruction const&) override;
virtual void CVTDQ2PD_xmm1_xmm2m64(X86::Instruction const&) override;
virtual void PMULUDQ_mm1_mm2m64(X86::Instruction const&) override;
virtual void PMULUDQ_mm1_mm2m128(X86::Instruction const&) override;
virtual void PSUBQ_mm1_mm2m64(X86::Instruction const&) override;
virtual void wrap_0xC0(const X86::Instruction&) override;
virtual void wrap_0xC1_16(const X86::Instruction&) override;
virtual void wrap_0xC1_32(const X86::Instruction&) override;

View file

@ -21,6 +21,7 @@ InstructionDescriptor s_0f_table32[256];
InstructionDescriptor s_sse_table_np[256];
InstructionDescriptor s_sse_table_66[256];
InstructionDescriptor s_sse_table_f3[256];
InstructionDescriptor s_sse_table_f2[256];
static bool opcode_has_register_index(u8 op)
{
@ -68,6 +69,7 @@ static void build(InstructionDescriptor* table, u8 op, char const* mnemonic, Ins
case OP_mm1_mm2m64_imm8:
case OP_reg_mm1_imm8:
case OP_mm1_r32m16_imm8:
case OP_xmm1_imm8:
case OP_xmm1_xmm2m32_imm8:
case OP_xmm1_xmm2m128_imm8:
case OP_reg_xmm1_imm8:
@ -169,9 +171,14 @@ static void build(InstructionDescriptor* table, u8 op, char const* mnemonic, Ins
case OP_xmm1_m64:
case OP_m64_xmm2:
case OP_rm8_xmm2m32:
case OP_r32_xmm2m64:
case OP_rm32_xmm2:
case OP_xmm1_mm2m64:
case OP_xmm_mm:
case OP_mm_xmm:
case OP_mm1m64_xmm2:
case OP_mm1_xmm2m64:
case OP_mm1_xmm2m128:
case OP_r32_xmm2m32:
case __EndFormatsWithRMByte:
case OP_CS:
@ -309,15 +316,12 @@ static void build_slash_reg(u8 op, u8 slash, char const* mnemonic, InstructionFo
static void build_sse_np(u8 op, char const* mnemonic, InstructionFormat format, InstructionHandler impl, IsLockPrefixAllowed lock_prefix_allowed = LockPrefixNotAllowed)
{
if (s_0f_table32[op].format == InvalidFormat) {
build_0f(op, mnemonic, format, impl, lock_prefix_allowed);
build(s_sse_table_np, op, mnemonic, format, impl, lock_prefix_allowed);
return;
}
if (s_0f_table32[op].format != __SSE)
build_0f(op, "__SSE_temp", __SSE, nullptr, lock_prefix_allowed);
VERIFY(s_0f_table32[op].format == __SSE);
VERIFY(s_sse_table_np[op].format == InvalidFormat);
build(s_sse_table_np, op, mnemonic, format, impl, lock_prefix_allowed);
}
@ -326,6 +330,8 @@ static void build_sse_66(u8 op, char const* mnemonic, InstructionFormat format,
if (s_0f_table32[op].format != __SSE)
build_0f(op, "__SSE_temp", __SSE, nullptr, lock_prefix_allowed);
VERIFY(s_0f_table32[op].format == __SSE);
VERIFY(s_sse_table_66[op].format == InvalidFormat);
build(s_sse_table_66, op, mnemonic, format, impl, lock_prefix_allowed);
}
@ -334,9 +340,38 @@ static void build_sse_f3(u8 op, char const* mnemonic, InstructionFormat format,
if (s_0f_table32[op].format != __SSE)
build_0f(op, "__SSE_temp", __SSE, nullptr, lock_prefix_allowed);
VERIFY(s_0f_table32[op].format == __SSE);
VERIFY(s_sse_table_f3[op].format == InvalidFormat);
build(s_sse_table_f3, op, mnemonic, format, impl, lock_prefix_allowed);
}
static void build_sse_f2(u8 op, char const* mnemonic, InstructionFormat format, InstructionHandler impl, IsLockPrefixAllowed lock_prefix_allowed = LockPrefixNotAllowed)
{
if (s_0f_table32[op].format != __SSE)
build_0f(op, "__SSE_temp", __SSE, nullptr, lock_prefix_allowed);
VERIFY(s_0f_table32[op].format == __SSE);
VERIFY(s_sse_table_f2[op].format == InvalidFormat);
build(s_sse_table_f2, op, mnemonic, format, impl, lock_prefix_allowed);
}
static void build_sse_np_slash(u8 op, u8 slash, char const* mnemonic, InstructionFormat format, InstructionHandler impl, IsLockPrefixAllowed lock_prefix_allowed = LockPrefixNotAllowed)
{
if (s_0f_table32[op].format != __SSE)
build_0f(op, "__SSE_temp", __SSE, nullptr, lock_prefix_allowed);
VERIFY(s_0f_table32[op].format == __SSE);
build_slash(s_sse_table_np, op, slash, mnemonic, format, impl, lock_prefix_allowed);
}
static void build_sse_66_slash(u8 op, u8 slash, char const* mnemonic, InstructionFormat format, InstructionHandler impl, IsLockPrefixAllowed lock_prefix_allowed = LockPrefixNotAllowed)
{
if (s_0f_table32[op].format != __SSE)
build_0f(op, "__SSE_temp", __SSE, nullptr, lock_prefix_allowed);
VERIFY(s_0f_table32[op].format == __SSE);
build_slash(s_sse_table_66, op, slash, mnemonic, format, impl, lock_prefix_allowed);
}
[[gnu::constructor]] static void build_opcode_tables()
{
build(0x00, "ADD", OP_RM8_reg8, &Interpreter::ADD_RM8_reg8, LockPrefixAllowed);
@ -845,14 +880,23 @@ static void build_sse_f3(u8 op, char const* mnemonic, InstructionFormat format,
build_0f(0x0B, "UD2", OP, &Interpreter::UD2);
build_sse_np(0x10, "MOVUPS", OP_xmm1_xmm2m128, &Interpreter::MOVUPS_xmm1_xmm2m128);
build_sse_66(0x10, "MOVUPD", OP_xmm1_xmm2m128, &Interpreter::MOVUPD_xmm1_xmm2m128);
build_sse_f3(0x10, "MOVSS", OP_xmm1_xmm2m32, &Interpreter::MOVSS_xmm1_xmm2m32);
build_sse_f2(0x10, "MOVSD", OP_xmm1_xmm2m32, &Interpreter::MOVSD_xmm1_xmm2m32);
build_sse_np(0x11, "MOVUPS", OP_xmm1m128_xmm2, &Interpreter::MOVUPS_xmm1m128_xmm2);
build_sse_66(0x11, "MOVUPD", OP_xmm1m128_xmm2, &Interpreter::MOVUPD_xmm1m128_xmm2);
build_sse_f3(0x11, "MOVSS", OP_xmm1m32_xmm2, &Interpreter::MOVSS_xmm1m32_xmm2);
build_sse_f2(0x11, "MOVSD", OP_xmm1m32_xmm2, &Interpreter::MOVSD_xmm1m32_xmm2);
build_sse_np(0x12, "MOVLPS", OP_xmm1_xmm2m64, &Interpreter::MOVLPS_xmm1_xmm2m64); // FIXME: This mnemonic is MOVHLPS when providing xmm2
build_sse_66(0x12, "MOVLPD", OP_xmm1_m64, &Interpreter::MOVLPD_xmm1_m64);
build_sse_np(0x13, "MOVLPS", OP_m64_xmm2, &Interpreter::MOVLPS_m64_xmm2);
build_sse_np(0x14, "UNPCKLS", OP_xmm1_xmm2m128, &Interpreter::UNPCKLPS_xmm1_xmm2m128);
build_sse_np(0x15, "UNPCKHS", OP_xmm1_xmm2m128, &Interpreter::UNPCKHPS_xmm1_xmm2m128);
build_sse_66(0x13, "MOVLPD", OP_m64_xmm2, &Interpreter::MOVLPD_m64_xmm2);
build_sse_np(0x14, "UNPCKLPS", OP_xmm1_xmm2m128, &Interpreter::UNPCKLPS_xmm1_xmm2m128);
build_sse_66(0x14, "UNPCKLPD", OP_xmm1_xmm2m128, &Interpreter::UNPCKLPD_xmm1_xmm2m128);
build_sse_np(0x15, "UNPCKHPS", OP_xmm1_xmm2m128, &Interpreter::UNPCKHPS_xmm1_xmm2m128);
build_sse_66(0x15, "UNPCKHPD", OP_xmm1_xmm2m128, &Interpreter::UNPCKHPD_xmm1_xmm2m128);
build_sse_np(0x16, "MOVHPS", OP_xmm1_xmm2m64, &Interpreter::MOVHPS_xmm1_xmm2m64); // FIXME: This mnemonic is MOVLHPS when providing xmm2
build_sse_66(0x16, "MOVHPD", OP_xmm1_xmm2m64, &Interpreter::MOVHPD_xmm1_xmm2m64); // FIXME: This mnemonic is MOVLHPS when providing xmm2
build_sse_np(0x17, "MOVHPS", OP_m64_xmm2, &Interpreter::MOVHPS_m64_xmm2);
build_0f(0x20, "MOV", OP_reg32_CR, &Interpreter::MOV_reg32_CR);
@ -861,17 +905,27 @@ static void build_sse_f3(u8 op, char const* mnemonic, InstructionFormat format,
build_0f(0x23, "MOV", OP_DR_reg32, &Interpreter::MOV_DR_reg32);
build_sse_np(0x28, "MOVAPS", OP_xmm1_xmm2m128, &Interpreter::MOVAPS_xmm1_xmm2m128);
build_sse_66(0x28, "MOVAPD", OP_xmm1_xmm2m128, &Interpreter::MOVAPD_xmm1_xmm2m128);
build_sse_np(0x29, "MOVAPS", OP_xmm1m128_xmm2, &Interpreter::MOVAPS_xmm1m128_xmm2);
build_sse_66(0x29, "MOVAPD", OP_xmm1m128_xmm2, &Interpreter::MOVAPD_xmm1m128_xmm2);
build_sse_np(0x2A, "CVTPI2PS", OP_xmm1_mm2m64, &Interpreter::CVTPI2PS_xmm1_mm2m64);
build_sse_66(0x2A, "CVTPI2PD", OP_xmm1_mm2m64, &Interpreter::CVTPI2PD_xmm1_mm2m64);
build_sse_f3(0x2A, "CVTSI2SS", OP_xmm1_rm32, &Interpreter::CVTSI2SS_xmm1_rm32);
build_sse_f2(0x2A, "CVTSI2SD", OP_xmm1_rm32, &Interpreter::CVTSI2SD_xmm1_rm32);
build_sse_np(0x2B, "MOVNTPS", OP_xmm1m128_xmm2, &Interpreter::MOVNTPS_xmm1m128_xmm2);
build_sse_np(0x2C, "CVTTPS2PI", OP_mm1_xmm2m64, &Interpreter::CVTTPS2PI_mm1_xmm2m64);
build_sse_66(0x2C, "CVTTPD2PI", OP_mm1_xmm2m128, &Interpreter::CVTTPD2PI_mm1_xmm2m128);
build_sse_f3(0x2C, "CVTTSS2SI", OP_r32_xmm2m32, &Interpreter::CVTTSS2SI_r32_xmm2m32);
build_sse_f2(0x2C, "CVTTSD2SI", OP_r32_xmm2m64, &Interpreter::CVTTSS2SI_r32_xmm2m64);
build_sse_np(0x2D, "CVTPS2PI", OP_mm1_xmm2m64, &Interpreter::CVTPS2PI_xmm1_mm2m64);
build_sse_66(0x2D, "CVTPD2PI", OP_mm1_xmm2m128, &Interpreter::CVTPD2PI_xmm1_mm2m128);
build_sse_f3(0x2D, "CVTSS2SI", OP_r32_xmm2m32, &Interpreter::CVTSS2SI_r32_xmm2m32);
build_sse_f2(0x2D, "CVTSD2SI", OP_r32_xmm2m64, &Interpreter::CVTSD2SI_xmm1_rm64);
build_sse_np(0x2E, "UCOMISS", OP_xmm1_xmm2m32, &Interpreter::UCOMISS_xmm1_xmm2m32);
build_sse_66(0x2E, "UCOMISD", OP_xmm1_xmm2m64, &Interpreter::UCOMISD_xmm1_xmm2m64);
build_sse_np(0x2F, "COMISS", OP_xmm1_xmm2m32, &Interpreter::COMISS_xmm1_xmm2m32);
build_sse_66(0x2F, "COMISD", OP_xmm1_xmm2m64, &Interpreter::COMISD_xmm1_xmm2m64);
build_0f(0x31, "RDTSC", OP, &Interpreter::RDTSC);
@ -893,30 +947,56 @@ static void build_sse_f3(u8 op, char const* mnemonic, InstructionFormat format,
build_0f(0x4F, "CMOVG", OP_reg16_RM16, &Interpreter::CMOVcc_reg16_RM16, OP_reg32_RM32, &Interpreter::CMOVcc_reg32_RM32);
build_sse_np(0x50, "MOVMSKPS", OP_reg_xmm1, &Interpreter::MOVMSKPS_reg_xmm);
build_sse_66(0x50, "MOVMSKPD", OP_reg_xmm1, &Interpreter::MOVMSKPD_reg_xmm);
build_sse_np(0x51, "SQRTPS", OP_xmm1_xmm2m128, &Interpreter::SQRTPS_xmm1_xmm2m128);
build_sse_66(0x51, "SQRTPD", OP_xmm1_xmm2m128, &Interpreter::SQRTPD_xmm1_xmm2m128);
build_sse_f3(0x51, "SQRTSS", OP_xmm1_xmm2m32, &Interpreter::SQRTSS_xmm1_xmm2m32);
build_sse_f2(0x51, "SQRTSD", OP_xmm1_xmm2m32, &Interpreter::SQRTSD_xmm1_xmm2m32);
build_sse_np(0x52, "RSQRTPS", OP_xmm1_xmm2m128, &Interpreter::RSQRTPS_xmm1_xmm2m128);
build_sse_f3(0x52, "RSQRTSS", OP_xmm1_xmm2m32, &Interpreter::RSQRTSS_xmm1_xmm2m32);
build_sse_np(0x53, "RCPPS", OP_xmm1_xmm2m128, &Interpreter::RCPPS_xmm1_xmm2m128);
build_sse_f3(0x53, "RCPSS", OP_xmm1_xmm2m32, &Interpreter::RCPSS_xmm1_xmm2m32);
build_sse_np(0x54, "ANDPS", OP_xmm1_xmm2m128, &Interpreter::ANDPS_xmm1_xmm2m128);
build_sse_66(0x54, "ANDPD", OP_xmm1_xmm2m128, &Interpreter::ANDPD_xmm1_xmm2m128);
build_sse_np(0x55, "ANDNPS", OP_xmm1_xmm2m128, &Interpreter::ANDNPS_xmm1_xmm2m128);
build_sse_66(0x55, "ANDNPD", OP_xmm1_xmm2m128, &Interpreter::ANDNPD_xmm1_xmm2m128);
build_sse_np(0x56, "ORPS", OP_xmm1_xmm2m128, &Interpreter::ORPS_xmm1_xmm2m128);
build_sse_66(0x56, "ORPD", OP_xmm1_xmm2m128, &Interpreter::ORPD_xmm1_xmm2m128);
build_sse_np(0x57, "XORPS", OP_xmm1_xmm2m128, &Interpreter::XORPS_xmm1_xmm2m128);
build_sse_66(0x57, "XORPD", OP_xmm1_xmm2m128, &Interpreter::XORPD_xmm1_xmm2m128);
build_sse_np(0x58, "ADDPS", OP_xmm1_xmm2m128, &Interpreter::ADDPS_xmm1_xmm2m128);
build_sse_66(0x58, "ADDPD", OP_xmm1_xmm2m128, &Interpreter::ADDPD_xmm1_xmm2m128);
build_sse_f3(0x58, "ADDSS", OP_xmm1_xmm2m32, &Interpreter::ADDSS_xmm1_xmm2m32);
build_sse_f2(0x58, "ADDSD", OP_xmm1_xmm2m32, &Interpreter::ADDSD_xmm1_xmm2m32);
build_sse_np(0x59, "MULPS", OP_xmm1_xmm2m128, &Interpreter::MULPS_xmm1_xmm2m128);
build_sse_66(0x59, "MULPD", OP_xmm1_xmm2m128, &Interpreter::MULPD_xmm1_xmm2m128);
build_sse_f3(0x59, "MULSS", OP_xmm1_xmm2m32, &Interpreter::MULSS_xmm1_xmm2m32);
build_sse_f2(0x59, "MULSD", OP_xmm1_xmm2m32, &Interpreter::MULSD_xmm1_xmm2m32);
build_sse_np(0x5A, "CVTPS2PD", OP_xmm1_xmm2m64, &Interpreter::CVTPS2PD_xmm1_xmm2m64);
build_sse_66(0x5A, "CVTPD2PS", OP_xmm1_xmm2m128, &Interpreter::CVTPD2PS_xmm1_xmm2m128);
build_sse_f3(0x5A, "CVTSS2SD", OP_xmm1_xmm2m32, &Interpreter::CVTSS2SD_xmm1_xmm2m32);
build_sse_f2(0x5A, "CVTSD2SS", OP_xmm1_xmm2m64, &Interpreter::CVTSD2SS_xmm1_xmm2m64);
build_sse_np(0x5B, "CVTDQ2PS", OP_xmm1_xmm2m128, &Interpreter::CVTDQ2PS_xmm1_xmm2m128);
build_sse_66(0x5B, "CVTPS2DQ", OP_xmm1_xmm2m128, &Interpreter::CVTPS2DQ_xmm1_xmm2m128);
build_sse_f3(0x5B, "CVTTPS2DQ", OP_xmm1_xmm2m128, &Interpreter::CVTTPS2DQ_xmm1_xmm2m128);
build_sse_np(0x5C, "SUBPS", OP_xmm1_xmm2m128, &Interpreter::SUBPS_xmm1_xmm2m128);
build_sse_66(0x5C, "SUBPD", OP_xmm1_xmm2m128, &Interpreter::SUBPD_xmm1_xmm2m128);
build_sse_f3(0x5C, "SUBSS", OP_xmm1_xmm2m32, &Interpreter::SUBSS_xmm1_xmm2m32);
build_sse_f2(0x5C, "SUBSD", OP_xmm1_xmm2m32, &Interpreter::SUBSD_xmm1_xmm2m32);
build_sse_np(0x5D, "MINPS", OP_xmm1_xmm2m128, &Interpreter::MINPS_xmm1_xmm2m128);
build_sse_66(0x5D, "MINPD", OP_xmm1_xmm2m128, &Interpreter::MINPD_xmm1_xmm2m128);
build_sse_f3(0x5D, "MINSS", OP_xmm1_xmm2m32, &Interpreter::MINSS_xmm1_xmm2m32);
build_sse_f2(0x5D, "MINSD", OP_xmm1_xmm2m32, &Interpreter::MINSD_xmm1_xmm2m32);
build_sse_np(0x5E, "DIVPS", OP_xmm1_xmm2m128, &Interpreter::DIVPS_xmm1_xmm2m128);
build_sse_66(0x5E, "DIVPD", OP_xmm1_xmm2m128, &Interpreter::DIVPD_xmm1_xmm2m128);
build_sse_f3(0x5E, "DIVSS", OP_xmm1_xmm2m32, &Interpreter::DIVSS_xmm1_xmm2m32);
build_sse_f2(0x5E, "DIVSD", OP_xmm1_xmm2m32, &Interpreter::DIVSD_xmm1_xmm2m32);
build_sse_np(0x5F, "MAXPS", OP_xmm1_xmm2m128, &Interpreter::MAXPS_xmm1_xmm2m128);
build_sse_66(0x5F, "MAXPD", OP_xmm1_xmm2m128, &Interpreter::MAXPD_xmm1_xmm2m128);
build_sse_f3(0x5F, "MAXSS", OP_xmm1_xmm2m32, &Interpreter::MAXSS_xmm1_xmm2m32);
build_sse_f2(0x5F, "MAXSD", OP_xmm1_xmm2m32, &Interpreter::MAXSD_xmm1_xmm2m32);
build_0f(0x60, "PUNPCKLBW", OP_mm1_mm2m32, &Interpreter::PUNPCKLBW_mm1_mm2m32);
build_0f(0x61, "PUNPCKLWD", OP_mm1_mm2m32, &Interpreter::PUNPCKLWD_mm1_mm2m32);
@ -930,27 +1010,42 @@ static void build_sse_f3(u8 op, char const* mnemonic, InstructionFormat format,
build_0f(0x69, "PUNPCKHWD", OP_mm1_mm2m64, &Interpreter::PUNPCKHWD_mm1_mm2m64);
build_0f(0x6A, "PUNPCKHDQ", OP_mm1_mm2m64, &Interpreter::PUNPCKHDQ_mm1_mm2m64);
build_0f(0x6B, "PACKSSDW", OP_mm1_mm2m64, &Interpreter::PACKSSDW_mm1_mm2m64);
build_0f(0x6E, "MOVD", OP_mm1_rm32, &Interpreter::MOVD_mm1_rm32);
build_0f(0x6F, "MOVQ", OP_mm1_mm2m64, &Interpreter::MOVQ_mm1_mm2m64);
build_sse_66(0x6C, "PUNPCKLQDQ", OP_xmm1_xmm2m128, &Interpreter::PUNPCKLQDQ_xmm1_xmm2m128);
build_sse_66(0x6D, "PUNPCKHQDQ", OP_xmm1_xmm2m128, &Interpreter::PUNPCKHQDQ_xmm1_xmm2m128);
build_0f(0x6E, "MOVD", OP_mm1_rm32, &Interpreter::MOVD_mm1_rm32); // FIXME: REX.W -> MOVQ
build_sse_np(0x6F, "MOVQ", OP_mm1_mm2m64, &Interpreter::MOVQ_mm1_mm2m64);
build_sse_66(0x6F, "MOVDQA", OP_xmm1_xmm2m128, &Interpreter::MOVDQA_xmm1_xmm2m128);
build_sse_f3(0x6F, "MOVDQU", OP_xmm1_xmm2m128, &Interpreter::MOVDQU_xmm1_xmm2m128);
build_sse_np(0x70, "PSHUFW", OP_mm1_mm2m64_imm8, &Interpreter::PSHUFW_mm1_mm2m64_imm8);
build_0f_slash(0x71, 2, "PSRLW", OP_mm1_imm8, &Interpreter::PSRLW_mm1_mm2m64);
build_sse_66(0x70, "PSHUFD", OP_xmm1_xmm2m128_imm8, &Interpreter::PSHUFD_xmm1_xmm2m128_imm8);
build_sse_f3(0x70, "PSHUFHW", OP_xmm1_xmm2m128_imm8, &Interpreter::PSHUFHW_xmm1_xmm2m128_imm8);
build_sse_f2(0x70, "PSHUFLW", OP_xmm1_xmm2m128_imm8, &Interpreter::PSHUFLW_xmm1_xmm2m128_imm8);
build_0f_slash(0x71, 2, "PSRLW", OP_mm1_imm8, &Interpreter::PSRLW_mm1_imm8);
build_0f_slash(0x71, 4, "PSRAW", OP_mm1_imm8, &Interpreter::PSRAW_mm1_imm8);
build_0f_slash(0x71, 6, "PSLLW", OP_mm1_imm8, &Interpreter::PSLLD_mm1_imm8);
build_0f_slash(0x72, 2, "PSRLD", OP_mm1_imm8, &Interpreter::PSRLD_mm1_mm2m64);
build_0f_slash(0x72, 2, "PSRLD", OP_mm1_imm8, &Interpreter::PSRLD_mm1_imm8);
build_0f_slash(0x72, 4, "PSRAD", OP_mm1_imm8, &Interpreter::PSRAD_mm1_imm8);
build_0f_slash(0x72, 6, "PSLLW", OP_mm1_imm8, &Interpreter::PSLLW_mm1_imm8);
build_0f_slash(0x73, 2, "PSRLQ", OP_mm1_imm8, &Interpreter::PSRLQ_mm1_mm2m64);
build_0f_slash(0x73, 6, "PSLLQ", OP_mm1_imm8, &Interpreter::PSLLQ_mm1_imm8);
build_sse_np_slash(0x73, 2, "PSRLQ", OP_mm1_imm8, &Interpreter::PSRLQ_mm1_imm8);
build_sse_66_slash(0x73, 2, "PSRLQ", OP_xmm1_imm8, &Interpreter::PSRLQ_xmm1_imm8);
build_sse_66_slash(0x73, 3, "PSRLDQ", OP_xmm1_imm8, &Interpreter::PSRLDQ_xmm1_imm8);
build_sse_np_slash(0x73, 6, "PSLLQ", OP_mm1_imm8, &Interpreter::PSLLQ_mm1_imm8);
build_sse_66_slash(0x73, 6, "PSLLQ", OP_xmm1_imm8, &Interpreter::PSLLQ_xmm1_imm8);
build_sse_66_slash(0x73, 7, "PSLLDQ", OP_xmm1_imm8, &Interpreter::PSLLDQ_xmm1_imm8);
build_0f(0x74, "PCMPEQB", OP_mm1_mm2m64, &Interpreter::PCMPEQB_mm1_mm2m64);
build_0f(0x76, "PCMPEQD", OP_mm1_mm2m64, &Interpreter::PCMPEQD_mm1_mm2m64);
build_0f(0x75, "PCMPEQW", OP_mm1_mm2m64, &Interpreter::PCMPEQW_mm1_mm2m64);
build_0f(0x77, "EMMS", OP, &Interpreter::EMMS);
build_0f(0x7E, "MOVD", OP_rm32_mm2, &Interpreter::MOVD_rm32_mm2);
build_0f(0x7F, "MOVQ", OP_mm1m64_mm2, &Interpreter::MOVQ_mm1m64_mm2);
build_0f(0x76, "PCMPEQD", OP_mm1_mm2m64, &Interpreter::PCMPEQD_mm1_mm2m64);
build_0f(0x77, "EMMS", OP, &Interpreter::EMMS); // Technically NP
build_sse_np(0x7E, "MOVD", OP_rm32_mm2, &Interpreter::MOVD_rm32_mm2); // FIXME: REW.W -> MOVQ
build_sse_66(0x7E, "MOVD", OP_rm32_xmm2, &Interpreter::MOVD_rm32_xmm2); // FIXME: REW.W -> MOVQ
build_sse_f3(0x7E, "MOVQ", OP_xmm1_xmm2m128, &Interpreter::MOVQ_xmm1_xmm2m128);
build_sse_np(0x7F, "MOVQ", OP_mm1m64_mm2, &Interpreter::MOVQ_mm1m64_mm2);
build_sse_66(0x7F, "MOVDQA", OP_xmm1m128_xmm2, &Interpreter::MOVDQA_xmm1m128_xmm2);
build_sse_f3(0x7F, "MOVDQU", OP_xmm1m128_xmm2, &Interpreter::MOVDQU_xmm1m128_xmm2);
build_0f(0x80, "JO", OP_NEAR_imm, &Interpreter::Jcc_NEAR_imm);
build_0f(0x81, "JNO", OP_NEAR_imm, &Interpreter::Jcc_NEAR_imm);
@ -1015,13 +1110,16 @@ static void build_sse_f3(u8 op, char const* mnemonic, InstructionFormat format,
build_0f(0xC0, "XADD", OP_RM8_reg8, &Interpreter::XADD_RM8_reg8, LockPrefixAllowed);
build_0f(0xC1, "XADD", OP_RM16_reg16, &Interpreter::XADD_RM16_reg16, OP_RM32_reg32, &Interpreter::XADD_RM32_reg32, LockPrefixAllowed);
build_sse_np(0xC2, "CMPPS", OP_xmm1_xmm2m128_imm8, &Interpreter::CMPPS_xmm1_xmm2m128_imm8);
build_sse_66(0xC2, "CMPPD", OP_xmm1_xmm2m128_imm8, &Interpreter::CMPPD_xmm1_xmm2m128_imm8);
build_sse_f3(0xC2, "CMPSS", OP_xmm1_xmm2m32_imm8, &Interpreter::CMPSS_xmm1_xmm2m32_imm8);
build_sse_f2(0xC2, "CMPSD", OP_xmm1_xmm2m32_imm8, &Interpreter::CMPSD_xmm1_xmm2m32_imm8);
build_sse_np(0xC5, "PINSRW", OP_mm1_r32m16_imm8, &Interpreter::PINSRW_mm1_r32m16_imm8);
build_sse_66(0xC5, "PINSRW", OP_xmm1_r32m16_imm8, &Interpreter::PINSRW_xmm1_r32m16_imm8);
build_sse_np(0xC4, "PINSRW", OP_mm1_r32m16_imm8, &Interpreter::PINSRW_mm1_r32m16_imm8);
build_sse_66(0xC4, "PINSRW", OP_xmm1_r32m16_imm8, &Interpreter::PINSRW_xmm1_r32m16_imm8);
build_sse_np(0xC5, "PEXTRW", OP_reg_mm1_imm8, &Interpreter::PEXTRW_reg_mm1_imm8);
build_sse_66(0xC5, "PEXTRW", OP_reg_xmm1_imm8, &Interpreter::PEXTRW_reg_xmm1_imm8);
build_sse_np(0xC6, "SHUFPS", OP_xmm1_xmm2m128_imm8, &Interpreter::SHUFPS_xmm1_xmm2m128_imm8);
build_sse_66(0xC6, "SHUFPD", OP_xmm1_xmm2m128_imm8, &Interpreter::SHUFPD_xmm1_xmm2m128_imm8);
for (u8 i = 0xc8; i <= 0xcf; ++i)
build_0f(i, "BSWAP", OP_reg32, &Interpreter::BSWAP_reg32);
@ -1029,8 +1127,12 @@ static void build_sse_f3(u8 op, char const* mnemonic, InstructionFormat format,
build_0f(0xD1, "PSRLW", OP_mm1_mm2m64, &Interpreter::PSRLW_mm1_mm2m64);
build_0f(0xD2, "PSRLD", OP_mm1_mm2m64, &Interpreter::PSRLD_mm1_mm2m64);
build_0f(0xD3, "PSRLQ", OP_mm1_mm2m64, &Interpreter::PSRLQ_mm1_mm2m64);
build_0f(0xD4, "PADDQ", OP_mm1_mm2m64, &Interpreter::PADDQ_mm1_mm2m64);
build_0f(0xD5, "PMULLW", OP_mm1_mm2m64, &Interpreter::PMULLW_mm1_mm2m64);
build_sse_66(0xD6, "MOVQ", OP_xmm1m128_xmm2, &Interpreter::MOVQ_xmm1m128_xmm2);
build_sse_f3(0xD6, "MOVQ2DQ", OP_xmm_mm, &Interpreter::MOVQ2DQ_xmm_mm);
build_sse_f2(0xD6, "MOVDQ2Q", OP_mm_xmm, &Interpreter::MOVDQ2Q_mm_xmm);
build_sse_np(0xD7, "PMOVMSKB", OP_reg_mm1, &Interpreter::PMOVMSKB_reg_mm1);
build_sse_66(0xD7, "PMOVMSKB", OP_reg_xmm1, &Interpreter::PMOVMSKB_reg_xmm1);
@ -1055,6 +1157,9 @@ static void build_sse_f3(u8 op, char const* mnemonic, InstructionFormat format,
build_sse_66(0xE4, "PMULHUW ", OP_xmm1_xmm2m64, &Interpreter::PMULHUW_xmm1_xmm2m64);
build_0f(0xE5, "PMULHW", OP_mm1_mm2m64, &Interpreter::PMULHW_mm1_mm2m64);
build_sse_66(0xE6, "CVTTPD2DQ", OP_xmm1_xmm2m128, &Interpreter::CVTTPD2DQ_xmm1_xmm2m128);
build_sse_f2(0xE6, "CVTPD2DQ", OP_xmm1_xmm2m128, &Interpreter::CVTPD2DQ_xmm1_xmm2m128);
build_sse_f3(0xE6, "CVTDQ2PD", OP_xmm1_xmm2m64, &Interpreter::CVTDQ2PD_xmm1_xmm2m64);
build_sse_np(0xE7, "MOVNTQ", OP_mm1m64_mm2, &Interpreter::MOVNTQ_m64_mm1);
build_sse_np(0xEA, "PMINSB", OP_mm1_mm2m64, &Interpreter::PMINSB_mm1_mm2m64);
@ -1073,6 +1178,8 @@ static void build_sse_f3(u8 op, char const* mnemonic, InstructionFormat format,
build_0f(0xF1, "PSLLW", OP_mm1_mm2m64, &Interpreter::PSLLW_mm1_mm2m64);
build_0f(0xF2, "PSLLD", OP_mm1_mm2m64, &Interpreter::PSLLD_mm1_mm2m64);
build_0f(0xF3, "PSLLQ", OP_mm1_mm2m64, &Interpreter::PSLLQ_mm1_mm2m64);
build_sse_np(0xF4, "PMULUDQ", OP_mm1_mm2m64, &Interpreter::PMULUDQ_mm1_mm2m64);
build_sse_66(0xF4, "PMULUDQ", OP_xmm1_xmm2m128, &Interpreter::PMULUDQ_mm1_mm2m128);
build_0f(0xF5, "PMADDWD", OP_mm1_mm2m64, &Interpreter::PMADDWD_mm1_mm2m64);
build_sse_np(0xF6, "PSADBW", OP_mm1_mm2m64, &Interpreter::PSADBB_mm1_mm2m64);
build_sse_66(0xF6, "PSADBW", OP_xmm1_xmm2m128, &Interpreter::PSADBB_xmm1_xmm2m128);
@ -1080,6 +1187,7 @@ static void build_sse_f3(u8 op, char const* mnemonic, InstructionFormat format,
build_0f(0xF8, "PSUBB", OP_mm1_mm2m64, &Interpreter::PSUBB_mm1_mm2m64);
build_0f(0xF9, "PSUBW", OP_mm1_mm2m64, &Interpreter::PSUBW_mm1_mm2m64);
build_0f(0xFA, "PSUBD", OP_mm1_mm2m64, &Interpreter::PSUBD_mm1_mm2m64);
build_0f(0xFB, "PSUBQ", OP_mm1_mm2m64, &Interpreter::PSUBQ_mm1_mm2m64);
build_0f(0xFC, "PADDB", OP_mm1_mm2m64, &Interpreter::PADDB_mm1_mm2m64);
build_0f(0xFD, "PADDW", OP_mm1_mm2m64, &Interpreter::PADDW_mm1_mm2m64);
build_0f(0xFE, "PADDD", OP_mm1_mm2m64, &Interpreter::PADDD_mm1_mm2m64);
@ -1414,7 +1522,8 @@ String Instruction::to_string(u32 origin, SymbolProvider const* symbol_provider,
builder.appendff("{}: ", register_name(segment_prefix().value()));
if (has_address_size_override_prefix())
builder.append(m_a32 ? "a32 " : "a16 ");
if (has_operand_size_override_prefix())
// Note: SSE2 Uses this to change to doubles in SSE instruction or xmm registers in MMX instructions
if (has_operand_size_override_prefix() && !(m_descriptor->format > __SSE && m_descriptor->format < __EndFormatsWithRMByte))
builder.append(m_o32 ? "o32 " : "o16 ");
if (has_lock_prefix())
builder.append("lock ");
@ -1491,6 +1600,22 @@ void Instruction::to_string_internal(StringBuilder& builder, u32 origin, SymbolP
auto append_xmmrm64 = [&] { builder.append(m_modrm.to_string_xmm(*this)); };
auto append_xmmrm128 = [&] { builder.append(m_modrm.to_string_xmm(*this)); };
auto append_mm_or_xmm = [&] {
if (has_operand_size_override_prefix())
append_xmm();
else
append_mm();
};
auto append_mm_or_xmm_or_mem = [&] {
// FIXME: The sizes here dont fully match what is meant, but it does
// not really matter...
if (has_operand_size_override_prefix())
append_xmmrm128();
else
append_mmrm64();
};
auto append = [&](auto& content) { builder.append(content); };
auto append_moff = [&] {
builder.append('[');
@ -2008,19 +2133,19 @@ void Instruction::to_string_internal(StringBuilder& builder, u32 origin, SymbolP
break;
case OP_mm1_imm8:
append_mnemonic_space();
append_mm();
append_mm_or_xmm();
append(", ");
append_imm8();
break;
case OP_mm1_mm2m32:
append_mnemonic_space();
append_mm();
append_mm_or_xmm();
append(", ");
append_mmrm32();
append_mm_or_xmm_or_mem();
break;
case OP_mm1_rm32:
append_mnemonic_space();
append_mm();
append_mm_or_xmm();
append(", ");
append_rm32();
break;
@ -2028,25 +2153,25 @@ void Instruction::to_string_internal(StringBuilder& builder, u32 origin, SymbolP
append_mnemonic_space();
append_rm32();
append(", ");
append_mm();
append_mm_or_xmm();
break;
case OP_mm1_mm2m64:
append_mnemonic_space();
append_mm();
append_mm_or_xmm();
append(", ");
append_mmrm64();
append_mm_or_xmm_or_mem();
break;
case OP_mm1m64_mm2:
append_mnemonic_space();
append_mmrm64();
append_mm_or_xmm_or_mem();
append(", ");
append_mm();
append_mm_or_xmm();
break;
case OP_mm1_mm2m64_imm8:
append_mnemonic_space();
append_mm();
append_mm_or_xmm();
append(", ");
append_mmrm64();
append_mm_or_xmm_or_mem();
append(", ");
append_imm8();
break;
@ -2054,25 +2179,44 @@ void Instruction::to_string_internal(StringBuilder& builder, u32 origin, SymbolP
append_mnemonic_space();
append_rm32();
append(", ");
append_mm();
append_mm_or_xmm();
break;
case OP_reg_mm1_imm8:
append_mnemonic_space();
append_reg32();
append(", ");
append_mmrm64();
append_mm_or_xmm_or_mem();
append(", ");
append_imm8();
break;
case OP_mm1_r32m16_imm8:
append_mnemonic_space();
append_mm();
append_mm_or_xmm();
append_rm32(); // FIXME: r32m16
append(", ");
append_imm8();
break;
case __SSE:
break;
case OP_xmm_mm:
append_mnemonic_space();
append_xmm();
append(", ");
append_mmrm32(); // FIXME: No Memmory
break;
case OP_mm1_xmm2m128:
case OP_mm_xmm:
append_mnemonic_space();
append_mm();
append(", ");
append_xmmrm32(); // FIXME: No Memmory
break;
case OP_xmm1_imm8:
append_mnemonic_space();
append_xmm();
append(", ");
append_imm8();
break;
case OP_xmm1_xmm2m32:
append_mnemonic_space();
append_xmm();
@ -2126,11 +2270,18 @@ void Instruction::to_string_internal(StringBuilder& builder, u32 origin, SymbolP
append_xmm();
break;
case OP_reg_xmm1:
case OP_r32_xmm2m64:
append_mnemonic_space();
append_reg32();
append(", ");
append_xmmrm128(); // second entry in the rm byte
break;
case OP_rm32_xmm2:
append_mnemonic_space();
append_rm32();
append(", ");
append_xmm();
break;
case OP_reg_xmm1_imm8:
append_mnemonic_space();
append_reg32();

View file

@ -118,6 +118,7 @@ enum InstructionFormat {
OP_reg_mm1_imm8,
OP_mm1_r32m16_imm8,
OP_xmm1_imm8,
OP_xmm1_xmm2m32,
OP_xmm1_xmm2m64,
OP_xmm1_xmm2m128,
@ -128,14 +129,19 @@ enum InstructionFormat {
OP_xmm1m128_xmm2,
OP_reg_xmm1,
OP_reg_xmm1_imm8,
OP_r32_xmm2m32,
OP_r32_xmm2m64,
OP_rm32_xmm2,
OP_xmm1_rm32,
OP_xmm1_m64,
OP_m64_xmm2,
OP_rm8_xmm2m32,
OP_xmm_mm,
OP_xmm1_mm2m64,
OP_mm1m64_xmm2,
OP_mm_xmm,
OP_mm1_xmm2m64,
OP_r32_xmm2m32,
OP_mm1_xmm2m128,
OP_xmm1_r32m16_imm8,
__EndFormatsWithRMByte,

View file

@ -736,6 +736,80 @@ public:
virtual void PSADBB_xmm1_xmm2m128(Instruction const&) = 0;
virtual void MASKMOVQ_mm1_mm2m64(Instruction const&) = 0;
virtual void MOVUPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void MOVSD_xmm1_xmm2m32(Instruction const&) = 0;
virtual void MOVUPD_xmm1m128_xmm2(Instruction const&) = 0;
virtual void MOVSD_xmm1m32_xmm2(Instruction const&) = 0;
virtual void MOVLPD_xmm1_m64(Instruction const&) = 0;
virtual void MOVLPD_m64_xmm2(Instruction const&) = 0;
virtual void UNPCKLPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void UNPCKHPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void MOVHPD_xmm1_xmm2m64(Instruction const&) = 0;
virtual void MOVAPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void MOVAPD_xmm1m128_xmm2(Instruction const&) = 0;
virtual void CVTPI2PD_xmm1_mm2m64(Instruction const&) = 0;
virtual void CVTSI2SD_xmm1_rm32(Instruction const&) = 0;
virtual void CVTTPD2PI_mm1_xmm2m128(Instruction const&) = 0;
virtual void CVTTSS2SI_r32_xmm2m64(Instruction const&) = 0;
virtual void CVTPD2PI_xmm1_mm2m128(Instruction const&) = 0;
virtual void CVTSD2SI_xmm1_rm64(Instruction const&) = 0;
virtual void UCOMISD_xmm1_xmm2m64(Instruction const&) = 0;
virtual void COMISD_xmm1_xmm2m64(Instruction const&) = 0;
virtual void MOVMSKPD_reg_xmm(Instruction const&) = 0;
virtual void SQRTPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void SQRTSD_xmm1_xmm2m32(Instruction const&) = 0;
virtual void ANDPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void ANDNPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void ORPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void XORPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void ADDPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void ADDSD_xmm1_xmm2m32(Instruction const&) = 0;
virtual void MULPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void MULSD_xmm1_xmm2m32(Instruction const&) = 0;
virtual void CVTPS2PD_xmm1_xmm2m64(Instruction const&) = 0;
virtual void CVTPD2PS_xmm1_xmm2m128(Instruction const&) = 0;
virtual void CVTSS2SD_xmm1_xmm2m32(Instruction const&) = 0;
virtual void CVTSD2SS_xmm1_xmm2m64(Instruction const&) = 0;
virtual void CVTDQ2PS_xmm1_xmm2m128(Instruction const&) = 0;
virtual void CVTPS2DQ_xmm1_xmm2m128(Instruction const&) = 0;
virtual void CVTTPS2DQ_xmm1_xmm2m128(Instruction const&) = 0;
virtual void SUBPD_xmm1_xmm2m128(X86::Instruction const&) = 0;
virtual void SUBSD_xmm1_xmm2m32(X86::Instruction const&) = 0;
virtual void MINPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void MINSD_xmm1_xmm2m32(Instruction const&) = 0;
virtual void DIVPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void DIVSD_xmm1_xmm2m32(Instruction const&) = 0;
virtual void MAXPD_xmm1_xmm2m128(Instruction const&) = 0;
virtual void MAXSD_xmm1_xmm2m32(Instruction const&) = 0;
virtual void PUNPCKLQDQ_xmm1_xmm2m128(Instruction const&) = 0;
virtual void PUNPCKHQDQ_xmm1_xmm2m128(Instruction const&) = 0;
virtual void MOVDQA_xmm1_xmm2m128(Instruction const&) = 0;
virtual void MOVDQU_xmm1_xmm2m128(Instruction const&) = 0;
virtual void PSHUFD_xmm1_xmm2m128_imm8(Instruction const&) = 0;
virtual void PSHUFHW_xmm1_xmm2m128_imm8(Instruction const&) = 0;
virtual void PSHUFLW_xmm1_xmm2m128_imm8(Instruction const&) = 0;
virtual void PSRLQ_xmm1_imm8(Instruction const&) = 0;
virtual void PSRLDQ_xmm1_imm8(Instruction const&) = 0;
virtual void PSLLQ_xmm1_imm8(Instruction const&) = 0;
virtual void PSLLDQ_xmm1_imm8(Instruction const&) = 0;
virtual void MOVD_rm32_xmm2(Instruction const&) = 0;
virtual void MOVQ_xmm1_xmm2m128(Instruction const&) = 0;
virtual void MOVDQA_xmm1m128_xmm2(Instruction const&) = 0;
virtual void MOVDQU_xmm1m128_xmm2(Instruction const&) = 0;
virtual void CMPPD_xmm1_xmm2m128_imm8(Instruction const&) = 0;
virtual void CMPSD_xmm1_xmm2m32_imm8(Instruction const&) = 0;
virtual void SHUFPD_xmm1_xmm2m128_imm8(Instruction const&) = 0;
virtual void PADDQ_mm1_mm2m64(Instruction const&) = 0;
virtual void MOVQ_xmm1m128_xmm2(Instruction const&) = 0;
virtual void MOVQ2DQ_xmm_mm(Instruction const&) = 0;
virtual void MOVDQ2Q_mm_xmm(Instruction const&) = 0;
virtual void CVTTPD2DQ_xmm1_xmm2m128(Instruction const&) = 0;
virtual void CVTPD2DQ_xmm1_xmm2m128(Instruction const&) = 0;
virtual void CVTDQ2PD_xmm1_xmm2m64(Instruction const&) = 0;
virtual void PMULUDQ_mm1_mm2m64(Instruction const&) = 0;
virtual void PMULUDQ_mm1_mm2m128(Instruction const&) = 0;
virtual void PSUBQ_mm1_mm2m64(Instruction const&) = 0;
protected:
virtual ~Interpreter() = default;
};