mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 23:37:35 +00:00
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:
parent
5987f0a8f5
commit
3e3b677852
5 changed files with 414 additions and 35 deletions
|
@ -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();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue