mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 04:24:37 +03:00
[Bug] [Critical] [ABI] Update that fixes all problems discovered by comparison with LLVM-MC
Fixed POP Sreg instruction, which was incorrectly implemented to emit nothing Fixed CVTSD2SI, CVTSS2SI, CVTTSD2SI, and CVTTSS2SI instructions to not consider the size of the memory operand when calculagint REX.W prefix Fixed VCMPPD, VCMPPS, VCMPSD, VCMPSS, VPCMPEQ*, VPCMPGT* instructions to always force EVEX prefix when the first operand is K register Fixed ENDBR32 and ENDBR64 instructions (wrong opcode) Fixed CLRSSBSY and RSTORSSP instructions (wrong logic in Assembler) Fixed SLDT, SMSW, and STR instructions to not consider memory size when determining prefixes Fixed UD0 and UD1 instructions to consider both operands Fixed VCVTNE2PS2BF16, VCVTNEPS2BF16, and VDPBF16PS instructions (incorrect calculation of LL field) (AVX512) Fixed VCVTPD2DQ, VCVTPD2PS, VCVTPD2UDQ, VCVTQQ2PS, VCVTTOD2DQ, VCVTTPD2UDQ, VCVTUQQ2PS in AVX512 case (incorrect calculation of LL field) Fixed VGATHERPF* and VSCATTERPF* instructions (some instructions were encoded incorrectly by not considering the memory index register type in LL field) Fixed VPBLENDVB (incorrect calculation of LL field) Fixed VPEXTRW to use use a shorter encoding when possible (vpextrw r32, xmm, imm) Fixed VPSLLD, VPSLLQ, VPSLLW, VPSRAD, VPSRAQ, VPSRAW, VPSRLD, VPSRLQ, VPSRLW instructions to always force EVEX prefix when the instruction is RMI (AVX512) Fixed the accepted memory operand size of MMX PUNPCKL??? instructions from m64 to m32 (only affects validation) Added explicit forms to XSAVE* and XRSTOR* instructions Added HRESET and UINTR instructions Changed MOV and all ARITH instructions to output the same binary as LLVM in 'reg, reg' case (it used an alternative encoding initially) Renamed LRET to RETF Renamed VBLENDM* instructions to VPBLENDM* (the name was incorrect) Renamed VPBROADCASTMB2D to VPBROADCASTMW2D (the name was incorrect) Renamed SYSEXIT64 to SYSEXITQ and SYSRET64 to SYSRETQ Removed non-standard IRETW (use IRET, IRETD, or IRETQ to select the form)
This commit is contained in:
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@@ -83,10 +83,12 @@ jobs:
|
|||||||
- { title: "macos-10.15" , os: "macos-10.15" , cc: "gcc-9" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
|
- { title: "macos-10.15" , os: "macos-10.15" , cc: "gcc-9" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
|
||||||
- { title: "macos-10.15" , os: "macos-10.15" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
|
- { title: "macos-10.15" , os: "macos-10.15" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
|
||||||
- { title: "macos-10.15" , os: "macos-10.15" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
|
- { title: "macos-10.15" , os: "macos-10.15" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
|
||||||
- { title: "macos-11.0" , os: "macos-11.0" , cc: "gcc-10" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
|
|
||||||
- { title: "macos-11.0" , os: "macos-11.0" , cc: "gcc-10" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
|
# Disabled, because of GitHub actions infrastructure issues (builds not starting).
|
||||||
- { title: "macos-11.0" , os: "macos-11.0" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
|
#- { title: "macos-11.0" , os: "macos-11.0" , cc: "gcc-10" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
|
||||||
- { title: "macos-11.0" , os: "macos-11.0" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
|
#- { title: "macos-11.0" , os: "macos-11.0" , cc: "gcc-10" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
|
||||||
|
#- { title: "macos-11.0" , os: "macos-11.0" , cc: "clang" , arch: "x64", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
|
||||||
|
#- { title: "macos-11.0" , os: "macos-11.0" , cc: "clang" , arch: "x64", build_type: "Release", defs: "ASMJIT_TEST=ON" }
|
||||||
|
|
||||||
- { title: "windows" , os: "windows-latest", cc: "vs2019" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
|
- { title: "windows" , os: "windows-latest", cc: "vs2019" , arch: "x86", build_type: "Debug" , defs: "ASMJIT_TEST=ON" }
|
||||||
- { title: "windows" , os: "windows-latest", cc: "vs2019" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" }
|
- { title: "windows" , os: "windows-latest", cc: "vs2019" , arch: "x86", build_type: "Release", defs: "ASMJIT_TEST=ON" }
|
||||||
|
|||||||
@@ -437,14 +437,14 @@ public:
|
|||||||
if (immSize >= 4) {
|
if (immSize >= 4) {
|
||||||
emit32uLE(imm & 0xFFFFFFFFu);
|
emit32uLE(imm & 0xFFFFFFFFu);
|
||||||
imm >>= 32;
|
imm >>= 32;
|
||||||
immSize -= 4;
|
immSize = FastUInt8(immSize - 4u);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
uint32_t imm = uint32_t(immValue & 0xFFFFFFFFu);
|
uint32_t imm = uint32_t(immValue & 0xFFFFFFFFu);
|
||||||
if (immSize >= 4) {
|
if (immSize >= 4) {
|
||||||
emit32uLE(imm);
|
emit32uLE(imm);
|
||||||
imm = uint32_t(immValue >> 32);
|
imm = uint32_t(immValue >> 32);
|
||||||
immSize -= 4;
|
immSize = FastUInt8(immSize - 4u);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -697,7 +697,8 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(uint32_t instId, const Operand_& o0, c
|
|||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
|
|
||||||
case InstDB::kEncodingX86Op_Mod11RM_I8:
|
case InstDB::kEncodingX86Op_Mod11RM_I8:
|
||||||
if (ASMJIT_UNLIKELY(isign3 != ENC_OPS1(Imm)))
|
// The first operand must be immediate, we don't care of other operands as they could be implicit.
|
||||||
|
if (!o0.isImm())
|
||||||
goto InvalidInstruction;
|
goto InvalidInstruction;
|
||||||
|
|
||||||
rbReg = opcode.extractModRM();
|
rbReg = opcode.extractModRM();
|
||||||
@@ -755,11 +756,17 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(uint32_t instId, const Operand_& o0, c
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case InstDB::kEncodingX86M_NoMemSize:
|
||||||
|
if (o0.isReg())
|
||||||
|
opcode.addPrefixBySize(o0.size());
|
||||||
|
goto CaseX86M_NoSize;
|
||||||
|
|
||||||
case InstDB::kEncodingX86M:
|
case InstDB::kEncodingX86M:
|
||||||
opcode.addPrefixBySize(o0.size());
|
opcode.addPrefixBySize(o0.size());
|
||||||
ASMJIT_FALLTHROUGH;
|
ASMJIT_FALLTHROUGH;
|
||||||
|
|
||||||
case InstDB::kEncodingX86M_NoSize:
|
case InstDB::kEncodingX86M_NoSize:
|
||||||
|
CaseX86M_NoSize:
|
||||||
rbReg = o0.id();
|
rbReg = o0.id();
|
||||||
if (isign3 == ENC_OPS1(Reg))
|
if (isign3 == ENC_OPS1(Reg))
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
@@ -839,6 +846,13 @@ CaseX86M_GPB_MulDiv:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case InstDB::kEncodingX86M_Only_EDX_EAX:
|
||||||
|
if (isign3 == ENC_OPS3(Mem, Reg, Reg) && Reg::isGpd(o1, Gp::kIdDx) && Reg::isGpd(o2, Gp::kIdAx)) {
|
||||||
|
rmRel = &o0;
|
||||||
|
goto EmitX86M;
|
||||||
|
}
|
||||||
|
ASMJIT_FALLTHROUGH;
|
||||||
|
|
||||||
case InstDB::kEncodingX86M_Only:
|
case InstDB::kEncodingX86M_Only:
|
||||||
if (isign3 == ENC_OPS1(Mem)) {
|
if (isign3 == ENC_OPS1(Mem)) {
|
||||||
rmRel = &o0;
|
rmRel = &o0;
|
||||||
@@ -977,34 +991,27 @@ CaseX86M_GPB_MulDiv:
|
|||||||
|
|
||||||
case InstDB::kEncodingX86Arith:
|
case InstDB::kEncodingX86Arith:
|
||||||
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
||||||
opcode += 2;
|
|
||||||
opcode.addArithBySize(o0.size());
|
opcode.addArithBySize(o0.size());
|
||||||
|
|
||||||
if (o0.size() != o1.size())
|
if (o0.size() != o1.size())
|
||||||
goto OperandSizeMismatch;
|
goto OperandSizeMismatch;
|
||||||
|
|
||||||
opReg = o0.id();
|
rbReg = o0.id();
|
||||||
rbReg = o1.id();
|
opReg = o1.id();
|
||||||
|
|
||||||
if (o0.size() == 1) {
|
if (o0.size() == 1) {
|
||||||
FIXUP_GPB(o0, opReg);
|
FIXUP_GPB(o0, rbReg);
|
||||||
FIXUP_GPB(o1, rbReg);
|
FIXUP_GPB(o1, opReg);
|
||||||
|
|
||||||
if (!(options & Inst::kOptionModMR))
|
|
||||||
goto EmitX86R;
|
|
||||||
|
|
||||||
opcode -= 2;
|
|
||||||
std::swap(opReg, rbReg);
|
|
||||||
goto EmitX86R;
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (!(options & Inst::kOptionModMR))
|
|
||||||
goto EmitX86R;
|
|
||||||
|
|
||||||
opcode -= 2;
|
// MOD/MR: The default encoding used if not instructed otherwise..
|
||||||
std::swap(opReg, rbReg);
|
if (!(options & Inst::kOptionModRM))
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
}
|
|
||||||
|
// MOD/RM: Alternative encoding selected via instruction options.
|
||||||
|
opcode += 2;
|
||||||
|
std::swap(opReg, rbReg);
|
||||||
|
goto EmitX86R;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isign3 == ENC_OPS2(Reg, Mem)) {
|
if (isign3 == ENC_OPS2(Reg, Mem)) {
|
||||||
@@ -1211,7 +1218,7 @@ CaseX86M_GPB_MulDiv:
|
|||||||
if (o1.size() != 1)
|
if (o1.size() != 1)
|
||||||
goto EmitX86M;
|
goto EmitX86M;
|
||||||
|
|
||||||
FIXUP_GPB(o0, opReg);
|
FIXUP_GPB(o1, opReg);
|
||||||
goto EmitX86M;
|
goto EmitX86M;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1436,6 +1443,8 @@ CaseX86M_GPB_MulDiv:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isign3 == ENC_OPS1(Mem)) {
|
if (isign3 == ENC_OPS1(Mem)) {
|
||||||
|
if (!o0.size())
|
||||||
|
goto AmbiguousOperandSize;
|
||||||
opcode.addArithBySize(o0.size());
|
opcode.addArithBySize(o0.size());
|
||||||
rmRel = &o0;
|
rmRel = &o0;
|
||||||
goto EmitX86M;
|
goto EmitX86M;
|
||||||
@@ -1539,9 +1548,6 @@ CaseX86M_GPB_MulDiv:
|
|||||||
case InstDB::kEncodingX86Mov:
|
case InstDB::kEncodingX86Mov:
|
||||||
// Reg <- Reg
|
// Reg <- Reg
|
||||||
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
||||||
opReg = o0.id();
|
|
||||||
rbReg = o1.id();
|
|
||||||
|
|
||||||
// Asmjit uses segment registers indexed from 1 to 6, leaving zero as
|
// Asmjit uses segment registers indexed from 1 to 6, leaving zero as
|
||||||
// "no segment register used". We have to fix this (decrement the index
|
// "no segment register used". We have to fix this (decrement the index
|
||||||
// of the register) when emitting MOV instructions which move to/from
|
// of the register) when emitting MOV instructions which move to/from
|
||||||
@@ -1550,47 +1556,46 @@ CaseX86M_GPB_MulDiv:
|
|||||||
|
|
||||||
// GP <- ??
|
// GP <- ??
|
||||||
if (Reg::isGp(o0)) {
|
if (Reg::isGp(o0)) {
|
||||||
|
rbReg = o0.id();
|
||||||
|
opReg = o1.id();
|
||||||
|
|
||||||
// GP <- GP
|
// GP <- GP
|
||||||
if (Reg::isGp(o1)) {
|
if (Reg::isGp(o1)) {
|
||||||
uint32_t size0 = o0.size();
|
uint32_t opSize = o0.size();
|
||||||
uint32_t size1 = o1.size();
|
if (opSize != o1.size()) {
|
||||||
|
// TODO: [X86 Assembler] This is a non-standard extension, which should be removed.
|
||||||
if (size0 != size1) {
|
|
||||||
// We allow 'mov r64, r32' as it's basically zero-extend.
|
// We allow 'mov r64, r32' as it's basically zero-extend.
|
||||||
if (size0 == 8 && size1 == 4)
|
if (opSize == 8 && o1.size() == 4)
|
||||||
size0 = 4; // Zero extend, don't promote to 64-bit.
|
opSize = 4; // Zero extend, don't promote to 64-bit.
|
||||||
else
|
else
|
||||||
goto InvalidInstruction;
|
goto InvalidInstruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size0 == 1) {
|
if (opSize == 1) {
|
||||||
FIXUP_GPB(o0, opReg);
|
FIXUP_GPB(o0, rbReg);
|
||||||
FIXUP_GPB(o1, rbReg);
|
FIXUP_GPB(o1, opReg);
|
||||||
opcode = 0x8A;
|
opcode = 0x88;
|
||||||
|
|
||||||
if (!(options & Inst::kOptionModMR))
|
if (!(options & Inst::kOptionModRM))
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
|
|
||||||
opcode -= 2;
|
opcode += 2;
|
||||||
std::swap(opReg, rbReg);
|
std::swap(opReg, rbReg);
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
opcode = 0x8B;
|
opcode = 0x89;
|
||||||
opcode.addPrefixBySize(size0);
|
opcode.addPrefixBySize(opSize);
|
||||||
|
|
||||||
if (!(options & Inst::kOptionModMR))
|
if (!(options & Inst::kOptionModRM))
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
|
|
||||||
opcode -= 2;
|
opcode += 2;
|
||||||
std::swap(opReg, rbReg);
|
std::swap(opReg, rbReg);
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opReg = rbReg;
|
|
||||||
rbReg = o0.id();
|
|
||||||
|
|
||||||
// GP <- SReg
|
// GP <- SReg
|
||||||
if (Reg::isSReg(o1)) {
|
if (Reg::isSReg(o1)) {
|
||||||
opcode = 0x8C;
|
opcode = 0x8C;
|
||||||
@@ -1618,6 +1623,9 @@ CaseX86M_GPB_MulDiv:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
opReg = o0.id();
|
||||||
|
rbReg = o1.id();
|
||||||
|
|
||||||
// ?? <- GP
|
// ?? <- GP
|
||||||
if (!Reg::isGp(o1))
|
if (!Reg::isGp(o1))
|
||||||
goto InvalidInstruction;
|
goto InvalidInstruction;
|
||||||
@@ -1952,7 +1960,7 @@ CaseX86M_GPB_MulDiv:
|
|||||||
goto InvalidSegment;
|
goto InvalidSegment;
|
||||||
|
|
||||||
opcode = x86OpcodePopSReg[segment];
|
opcode = x86OpcodePopSReg[segment];
|
||||||
goto EmitDone;
|
goto EmitX86Op;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CaseX86PushPop_Gp:
|
CaseX86PushPop_Gp:
|
||||||
@@ -2032,6 +2040,8 @@ CaseX86PushPop_Gp:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
if (ASMJIT_UNLIKELY(o0.size() == 0))
|
||||||
|
goto AmbiguousOperandSize;
|
||||||
opcode.addArithBySize(o0.size());
|
opcode.addArithBySize(o0.size());
|
||||||
|
|
||||||
if (isign3 == ENC_OPS2(Mem, Reg)) {
|
if (isign3 == ENC_OPS2(Mem, Reg)) {
|
||||||
@@ -2044,9 +2054,6 @@ CaseX86PushPop_Gp:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isign3 == ENC_OPS2(Mem, Imm)) {
|
if (isign3 == ENC_OPS2(Mem, Imm)) {
|
||||||
if (ASMJIT_UNLIKELY(o0.size() == 0))
|
|
||||||
goto AmbiguousOperandSize;
|
|
||||||
|
|
||||||
rmRel = &o0;
|
rmRel = &o0;
|
||||||
immValue = o1.as<Imm>().value() & 0xFF;
|
immValue = o1.as<Imm>().value() & 0xFF;
|
||||||
immSize = 0;
|
immSize = 0;
|
||||||
@@ -2257,30 +2264,45 @@ CaseX86PushPop_Gp:
|
|||||||
|
|
||||||
case InstDB::kEncodingX86Xadd:
|
case InstDB::kEncodingX86Xadd:
|
||||||
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
||||||
opcode.addArithBySize(o0.size());
|
|
||||||
rbReg = o0.id();
|
rbReg = o0.id();
|
||||||
opReg = o1.id();
|
opReg = o1.id();
|
||||||
|
|
||||||
if (o0.size() != o1.size())
|
uint32_t opSize = o0.size();
|
||||||
|
if (opSize != o1.size())
|
||||||
goto OperandSizeMismatch;
|
goto OperandSizeMismatch;
|
||||||
|
|
||||||
if (o0.size() == 1) {
|
if (opSize == 1) {
|
||||||
FIXUP_GPB(o0, rbReg);
|
FIXUP_GPB(o0, rbReg);
|
||||||
FIXUP_GPB(o1, opReg);
|
FIXUP_GPB(o1, opReg);
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special opcode for 'xchg ?ax, reg'.
|
// Special cases for 'xchg ?ax, reg'.
|
||||||
if (instId == Inst::kIdXchg && (opReg == 0 || rbReg == 0)) {
|
if (instId == Inst::kIdXchg && (opReg == 0 || rbReg == 0)) {
|
||||||
opcode &= Opcode::kPP_66 | Opcode::kW;
|
if (is64Bit() && opReg == rbReg && opSize >= 4) {
|
||||||
opcode |= 0x90;
|
if (opSize == 8) {
|
||||||
// One of `xchg a, b` or `xchg b, a` is AX/EAX/RAX.
|
// Encode 'xchg rax, rax' as '90' (REX and other prefixes are optional).
|
||||||
opReg += rbReg;
|
opcode &= Opcode::kW;
|
||||||
goto EmitX86OpReg;
|
opcode |= 0x90;
|
||||||
}
|
goto EmitX86OpReg;
|
||||||
else {
|
}
|
||||||
goto EmitX86R;
|
else {
|
||||||
|
// Encode 'xchg eax, eax' by by using a generic path.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!(options & Inst::kOptionLongForm)) {
|
||||||
|
// The special encoding encodes only one register, which is non-zero.
|
||||||
|
opReg += rbReg;
|
||||||
|
|
||||||
|
opcode.addArithBySize(opSize);
|
||||||
|
opcode &= Opcode::kW | Opcode::kPP_66;
|
||||||
|
opcode |= 0x90;
|
||||||
|
goto EmitX86OpReg;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
opcode.addArithBySize(opSize);
|
||||||
|
goto EmitX86R;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isign3 == ENC_OPS2(Mem, Reg)) {
|
if (isign3 == ENC_OPS2(Mem, Reg)) {
|
||||||
@@ -2700,7 +2722,11 @@ CaseExtMovd:
|
|||||||
goto CaseExtRm;
|
goto CaseExtRm;
|
||||||
|
|
||||||
case InstDB::kEncodingExtRm_Wx:
|
case InstDB::kEncodingExtRm_Wx:
|
||||||
opcode.addWIf(Reg::isGpq(o0) || o1.size() == 8);
|
opcode.addWIf(o1.size() == 8);
|
||||||
|
ASMJIT_FALLTHROUGH;
|
||||||
|
|
||||||
|
case InstDB::kEncodingExtRm_Wx_GpqOnly:
|
||||||
|
opcode.addWIf(Reg::isGpq(o0));
|
||||||
ASMJIT_FALLTHROUGH;
|
ASMJIT_FALLTHROUGH;
|
||||||
|
|
||||||
case InstDB::kEncodingExtRm:
|
case InstDB::kEncodingExtRm:
|
||||||
@@ -2843,15 +2869,15 @@ CaseExtRm:
|
|||||||
if (isign3 == ENC_OPS2(Reg, Reg))
|
if (isign3 == ENC_OPS2(Reg, Reg))
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
|
|
||||||
// The following instruction uses the secondary opcode.
|
|
||||||
opcode = x86AltOpcodeOf(instInfo);
|
|
||||||
|
|
||||||
if (isign3 == ENC_OPS3(Reg, Imm, Imm)) {
|
if (isign3 == ENC_OPS3(Reg, Imm, Imm)) {
|
||||||
|
// This variant of the instruction uses the secondary opcode.
|
||||||
|
opcode = x86AltOpcodeOf(instInfo);
|
||||||
|
rbReg = opReg;
|
||||||
|
opReg = opcode.extractModO();
|
||||||
|
|
||||||
immValue = (uint32_t(o1.as<Imm>().valueAs<uint8_t>()) ) +
|
immValue = (uint32_t(o1.as<Imm>().valueAs<uint8_t>()) ) +
|
||||||
(uint32_t(o2.as<Imm>().valueAs<uint8_t>()) << 8) ;
|
(uint32_t(o2.as<Imm>().valueAs<uint8_t>()) << 8) ;
|
||||||
immSize = 2;
|
immSize = 2;
|
||||||
|
|
||||||
rbReg = opcode.extractModO();
|
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2866,10 +2892,10 @@ CaseExtRm:
|
|||||||
if (isign4 == ENC_OPS2(Reg, Reg))
|
if (isign4 == ENC_OPS2(Reg, Reg))
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
|
|
||||||
// The following instruction uses the secondary opcode.
|
|
||||||
opcode = x86AltOpcodeOf(instInfo);
|
|
||||||
|
|
||||||
if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
|
if (isign4 == ENC_OPS4(Reg, Reg, Imm, Imm)) {
|
||||||
|
// This variant of the instruction uses the secondary opcode.
|
||||||
|
opcode = x86AltOpcodeOf(instInfo);
|
||||||
|
|
||||||
immValue = (uint32_t(o2.as<Imm>().valueAs<uint8_t>()) ) +
|
immValue = (uint32_t(o2.as<Imm>().valueAs<uint8_t>()) ) +
|
||||||
(uint32_t(o3.as<Imm>().valueAs<uint8_t>()) << 8) ;
|
(uint32_t(o3.as<Imm>().valueAs<uint8_t>()) << 8) ;
|
||||||
immSize = 2;
|
immSize = 2;
|
||||||
@@ -2971,7 +2997,6 @@ CaseExtRm:
|
|||||||
|
|
||||||
case InstDB::kEncodingVexM_VM:
|
case InstDB::kEncodingVexM_VM:
|
||||||
if (isign3 == ENC_OPS1(Mem)) {
|
if (isign3 == ENC_OPS1(Mem)) {
|
||||||
opcode |= x86OpcodeLByVMem(o0);
|
|
||||||
rmRel = &o0;
|
rmRel = &o0;
|
||||||
goto EmitVexEvexM;
|
goto EmitVexEvexM;
|
||||||
}
|
}
|
||||||
@@ -3003,11 +3028,27 @@ CaseExtRm:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case InstDB::kEncodingVexMri_Vpextrw:
|
||||||
|
// Use 'vpextrw reg, xmm1, i8' when possible.
|
||||||
|
if (isign3 == ENC_OPS3(Reg, Reg, Imm)) {
|
||||||
|
opcode = Opcode::k660F00 | 0xC5;
|
||||||
|
|
||||||
|
opReg = o0.id();
|
||||||
|
rbReg = o1.id();
|
||||||
|
|
||||||
|
immValue = o2.as<Imm>().value();
|
||||||
|
immSize = 1;
|
||||||
|
goto EmitVexEvexR;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto CaseVexMri;
|
||||||
|
|
||||||
case InstDB::kEncodingVexMri_Lx:
|
case InstDB::kEncodingVexMri_Lx:
|
||||||
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
||||||
ASMJIT_FALLTHROUGH;
|
ASMJIT_FALLTHROUGH;
|
||||||
|
|
||||||
case InstDB::kEncodingVexMri:
|
case InstDB::kEncodingVexMri:
|
||||||
|
CaseVexMri:
|
||||||
immValue = o2.as<Imm>().value();
|
immValue = o2.as<Imm>().value();
|
||||||
immSize = 1;
|
immSize = 1;
|
||||||
|
|
||||||
@@ -3035,6 +3076,13 @@ CaseExtRm:
|
|||||||
opcode.addWIf(Reg::isGpq(o0) | Reg::isGpq(o1));
|
opcode.addWIf(Reg::isGpq(o0) | Reg::isGpq(o1));
|
||||||
goto CaseVexRm;
|
goto CaseVexRm;
|
||||||
|
|
||||||
|
case InstDB::kEncodingVexRm_Lx_Narrow:
|
||||||
|
if (o1.size())
|
||||||
|
opcode |= x86OpcodeLBySize(o1.size());
|
||||||
|
else if (o0.size() == 32)
|
||||||
|
opcode |= Opcode::kLL_2;
|
||||||
|
goto CaseVexRm;
|
||||||
|
|
||||||
case InstDB::kEncodingVexRm_Lx_Bcst:
|
case InstDB::kEncodingVexRm_Lx_Bcst:
|
||||||
if (isign3 == ENC_OPS2(Reg, Reg) && Reg::isGp(o1.as<Reg>())) {
|
if (isign3 == ENC_OPS2(Reg, Reg) && Reg::isGp(o1.as<Reg>())) {
|
||||||
opcode = x86AltOpcodeOf(instInfo) | x86OpcodeLBySize(o0.size() | o1.size());
|
opcode = x86AltOpcodeOf(instInfo) | x86OpcodeLBySize(o0.size() | o1.size());
|
||||||
@@ -3077,7 +3125,7 @@ CaseVexRm:
|
|||||||
const Operand_& o4 = opExt[EmitterUtils::kOp4];
|
const Operand_& o4 = opExt[EmitterUtils::kOp4];
|
||||||
const Operand_& o5 = opExt[EmitterUtils::kOp5];
|
const Operand_& o5 = opExt[EmitterUtils::kOp5];
|
||||||
|
|
||||||
if (Reg::isZmm(o0) && Reg::isZmm(o1) && Reg::isZmm(o2) && Reg::isZmm(o3) && Reg::isZmm(o4) && o5.isMem()) {
|
if (Reg::isVec(o0) && Reg::isVec(o1) && Reg::isVec(o2) && Reg::isVec(o3) && Reg::isVec(o4) && o5.isMem()) {
|
||||||
// Registers [o1, o2, o3, o4] must start aligned and must be consecutive.
|
// Registers [o1, o2, o3, o4] must start aligned and must be consecutive.
|
||||||
uint32_t i1 = o1.id();
|
uint32_t i1 = o1.id();
|
||||||
uint32_t i2 = o2.id();
|
uint32_t i2 = o2.id();
|
||||||
@@ -3087,7 +3135,7 @@ CaseVexRm:
|
|||||||
if (ASMJIT_UNLIKELY((i1 & 0x3) != 0 || i2 != i1 + 1 || i3 != i1 + 2 || i4 != i1 + 3))
|
if (ASMJIT_UNLIKELY((i1 & 0x3) != 0 || i2 != i1 + 1 || i3 != i1 + 2 || i4 != i1 + 3))
|
||||||
goto NotConsecutiveRegs;
|
goto NotConsecutiveRegs;
|
||||||
|
|
||||||
opReg = o0.id();
|
opReg = x86PackRegAndVvvvv(o0.id(), i1);
|
||||||
rmRel = &o5;
|
rmRel = &o5;
|
||||||
goto EmitVexEvexM;
|
goto EmitVexEvexM;
|
||||||
}
|
}
|
||||||
@@ -3148,6 +3196,11 @@ CaseVexRvm_R:
|
|||||||
goto CaseVexRvm;
|
goto CaseVexRvm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case InstDB::kEncodingVexRvm_Lx_KEvex: {
|
||||||
|
opcode.forceEvexIf(Reg::isKReg(o0));
|
||||||
|
ASMJIT_FALLTHROUGH;
|
||||||
|
}
|
||||||
|
|
||||||
case InstDB::kEncodingVexRvm_Lx: {
|
case InstDB::kEncodingVexRvm_Lx: {
|
||||||
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
||||||
goto CaseVexRvm;
|
goto CaseVexRvm;
|
||||||
@@ -3205,11 +3258,21 @@ CaseVexRvm_R:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case InstDB::kEncodingVexRvmi_KEvex:
|
||||||
|
opcode.forceEvexIf(Reg::isKReg(o0));
|
||||||
|
goto VexRvmi;
|
||||||
|
|
||||||
|
case InstDB::kEncodingVexRvmi_Lx_KEvex:
|
||||||
|
opcode.forceEvexIf(Reg::isKReg(o0));
|
||||||
|
ASMJIT_FALLTHROUGH;
|
||||||
|
|
||||||
case InstDB::kEncodingVexRvmi_Lx:
|
case InstDB::kEncodingVexRvmi_Lx:
|
||||||
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
||||||
ASMJIT_FALLTHROUGH;
|
ASMJIT_FALLTHROUGH;
|
||||||
|
|
||||||
case InstDB::kEncodingVexRvmi: {
|
case InstDB::kEncodingVexRvmi:
|
||||||
|
VexRvmi:
|
||||||
|
{
|
||||||
const Operand_& o3 = opExt[EmitterUtils::kOp3];
|
const Operand_& o3 = opExt[EmitterUtils::kOp3];
|
||||||
const uint32_t isign4 = isign3 + (o3.opType() << 9);
|
const uint32_t isign4 = isign3 + (o3.opType() << 9);
|
||||||
|
|
||||||
@@ -3257,7 +3320,6 @@ CaseVexRvm_R:
|
|||||||
rmRel = &o1;
|
rmRel = &o1;
|
||||||
goto EmitVexEvexM;
|
goto EmitVexEvexM;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASMJIT_FALLTHROUGH;
|
ASMJIT_FALLTHROUGH;
|
||||||
|
|
||||||
case InstDB::kEncodingVexRmv_VM:
|
case InstDB::kEncodingVexRmv_VM:
|
||||||
@@ -3542,6 +3604,10 @@ CaseVexRvm_R:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case InstDB::kEncodingVexRvmVmi_Lx_MEvex:
|
||||||
|
opcode.forceEvexIf(o1.isMem());
|
||||||
|
ASMJIT_FALLTHROUGH;
|
||||||
|
|
||||||
case InstDB::kEncodingVexRvmVmi_Lx:
|
case InstDB::kEncodingVexRvmVmi_Lx:
|
||||||
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
||||||
ASMJIT_FALLTHROUGH;
|
ASMJIT_FALLTHROUGH;
|
||||||
@@ -3560,7 +3626,7 @@ CaseVexRvm_R:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The following instruction uses the secondary opcode.
|
// The following instruction uses the secondary opcode.
|
||||||
opcode &= Opcode::kLL_Mask;
|
opcode &= Opcode::kLL_Mask | Opcode::kMM_ForceEvex;
|
||||||
opcode |= x86AltOpcodeOf(instInfo);
|
opcode |= x86AltOpcodeOf(instInfo);
|
||||||
opReg = opcode.extractModO();
|
opReg = opcode.extractModO();
|
||||||
|
|
||||||
@@ -3598,9 +3664,9 @@ CaseVexRvm_R:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InstDB::kEncodingVexEvexVmi_Lx:
|
case InstDB::kEncodingVexVmi_Lx_MEvex:
|
||||||
if (isign3 == ENC_OPS3(Reg, Mem, Imm))
|
if (isign3 == ENC_OPS3(Reg, Mem, Imm))
|
||||||
opcode |= Opcode::kMM_ForceEvex;
|
opcode.forceEvex();
|
||||||
ASMJIT_FALLTHROUGH;
|
ASMJIT_FALLTHROUGH;
|
||||||
|
|
||||||
case InstDB::kEncodingVexVmi_Lx:
|
case InstDB::kEncodingVexVmi_Lx:
|
||||||
@@ -3743,11 +3809,24 @@ CaseVexVmi_AfterImm:
|
|||||||
|
|
||||||
if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
|
if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
|
||||||
opReg = x86PackRegAndVvvvv(o0.id(), o1.id());
|
opReg = x86PackRegAndVvvvv(o0.id(), o1.id());
|
||||||
rbReg = o2.id();
|
|
||||||
|
|
||||||
immValue = o3.id() << 4;
|
if (!(options & Inst::kOptionModMR)) {
|
||||||
immSize = 1;
|
// MOD/RM - Encoding preferred by LLVM.
|
||||||
goto EmitVexEvexR;
|
opcode.addW();
|
||||||
|
rbReg = o3.id();
|
||||||
|
|
||||||
|
immValue = o2.id() << 4;
|
||||||
|
immSize = 1;
|
||||||
|
goto EmitVexEvexR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// MOD/MR - Alternative encoding.
|
||||||
|
rbReg = o2.id();
|
||||||
|
|
||||||
|
immValue = o3.id() << 4;
|
||||||
|
immSize = 1;
|
||||||
|
goto EmitVexEvexR;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isign4 == ENC_OPS4(Reg, Reg, Reg, Mem)) {
|
if (isign4 == ENC_OPS4(Reg, Reg, Reg, Mem)) {
|
||||||
|
|||||||
@@ -340,9 +340,10 @@ public:
|
|||||||
//! \name Encoding Options
|
//! \name Encoding Options
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
//! Prefer MOD_MR encoding over MOD_RM (the default) when encoding instruction
|
//! Prefer MOD/RM encoding when both MOD/RM and MOD/MR forms are applicable.
|
||||||
//! that allows both. This option is only applicable to instructions where both
|
inline This& mod_rm() noexcept { return _addInstOptions(Inst::kOptionModRM); }
|
||||||
//! operands are registers.
|
|
||||||
|
//! Prefer MOD/MR encoding when both MOD/RM and MOD/MR forms are applicable.
|
||||||
inline This& mod_mr() noexcept { return _addInstOptions(Inst::kOptionModMR); }
|
inline This& mod_mr() noexcept { return _addInstOptions(Inst::kOptionModMR); }
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
@@ -675,10 +676,10 @@ public:
|
|||||||
ASMJIT_INST_2x(test, Test, Gp, Imm) // ANY
|
ASMJIT_INST_2x(test, Test, Gp, Imm) // ANY
|
||||||
ASMJIT_INST_2x(test, Test, Mem, Gp) // ANY
|
ASMJIT_INST_2x(test, Test, Mem, Gp) // ANY
|
||||||
ASMJIT_INST_2x(test, Test, Mem, Imm) // ANY
|
ASMJIT_INST_2x(test, Test, Mem, Imm) // ANY
|
||||||
ASMJIT_INST_1x(ud0, Ud0, Reg) // ANY
|
ASMJIT_INST_2x(ud0, Ud0, Gp, Gp) // ANY
|
||||||
ASMJIT_INST_1x(ud0, Ud0, Mem) // ANY
|
ASMJIT_INST_2x(ud0, Ud0, Gp, Mem) // ANY
|
||||||
ASMJIT_INST_1x(ud1, Ud1, Reg) // ANY
|
ASMJIT_INST_2x(ud1, Ud1, Gp, Gp) // ANY
|
||||||
ASMJIT_INST_1x(ud1, Ud1, Mem) // ANY
|
ASMJIT_INST_2x(ud1, Ud1, Gp, Mem) // ANY
|
||||||
ASMJIT_INST_0x(ud2, Ud2) // ANY
|
ASMJIT_INST_0x(ud2, Ud2) // ANY
|
||||||
ASMJIT_INST_2x(xadd, Xadd, Gp, Gp) // ANY
|
ASMJIT_INST_2x(xadd, Xadd, Gp, Gp) // ANY
|
||||||
ASMJIT_INST_2x(xadd, Xadd, Mem, Gp) // ANY
|
ASMJIT_INST_2x(xadd, Xadd, Mem, Gp) // ANY
|
||||||
@@ -993,7 +994,19 @@ public:
|
|||||||
//! \name XSAVE Instructions
|
//! \name XSAVE Instructions
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
ASMJIT_INST_3x(xgetbv, Xgetbv, Gp_EDX, Gp_EAX, Gp_ECX) // XSAVE [EXPLICIT] EDX:EAX <- XCR[ECX]
|
ASMJIT_INST_3x(xgetbv, Xgetbv, Gp_EDX, Gp_EAX, Gp_ECX) // XSAVE [EXPLICIT] EDX:EAX <- XCR[ECX]
|
||||||
|
ASMJIT_INST_3x(xrstor, Xrstor, Mem, Gp_EDX, Gp_EAX) // XSAVE [EXPLICIT]
|
||||||
|
ASMJIT_INST_3x(xrstor64, Xrstor64, Mem, Gp_EDX, Gp_EAX) // XSAVE+X64 [EXPLICIT]
|
||||||
|
ASMJIT_INST_3x(xrstors, Xrstors, Mem, Gp_EDX, Gp_EAX) // XSAVE [EXPLICIT]
|
||||||
|
ASMJIT_INST_3x(xrstors64, Xrstors64, Mem, Gp_EDX, Gp_EAX) // XSAVE+X64 [EXPLICIT]
|
||||||
|
ASMJIT_INST_3x(xsave, Xsave, Mem, Gp_EDX, Gp_EAX) // XSAVE [EXPLICIT]
|
||||||
|
ASMJIT_INST_3x(xsave64, Xsave64, Mem, Gp_EDX, Gp_EAX) // XSAVE+X64 [EXPLICIT]
|
||||||
|
ASMJIT_INST_3x(xsavec, Xsavec, Mem, Gp_EDX, Gp_EAX) // XSAVE [EXPLICIT]
|
||||||
|
ASMJIT_INST_3x(xsavec64, Xsavec64, Mem, Gp_EDX, Gp_EAX) // XSAVE+X64 [EXPLICIT]
|
||||||
|
ASMJIT_INST_3x(xsaveopt, Xsaveopt, Mem, Gp_EDX, Gp_EAX) // XSAVE [EXPLICIT]
|
||||||
|
ASMJIT_INST_3x(xsaveopt64, Xsaveopt64, Mem, Gp_EDX, Gp_EAX) // XSAVE+X64 [EXPLICIT]
|
||||||
|
ASMJIT_INST_3x(xsaves, Xsaves, Mem, Gp_EDX, Gp_EAX) // XSAVE [EXPLICIT]
|
||||||
|
ASMJIT_INST_3x(xsaves64, Xsaves64, Mem, Gp_EDX, Gp_EAX) // XSAVE+X64 [EXPLICIT]
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
@@ -1018,8 +1031,8 @@ public:
|
|||||||
//! \name MONITORX Instructions
|
//! \name MONITORX Instructions
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
ASMJIT_INST_3x(monitorx, Monitorx, Mem, Gp, Gp)
|
ASMJIT_INST_3x(monitorx, Monitorx, Mem, Gp, Gp) // MONITORX
|
||||||
ASMJIT_INST_3x(mwaitx, Mwaitx, Gp, Gp, Gp)
|
ASMJIT_INST_3x(mwaitx, Mwaitx, Gp, Gp, Gp) // MONITORX
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
@@ -1049,9 +1062,9 @@ public:
|
|||||||
//! \name WAITPKG Instructions
|
//! \name WAITPKG Instructions
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
ASMJIT_INST_3x(tpause, Tpause, Gp, Gp, Gp)
|
ASMJIT_INST_3x(tpause, Tpause, Gp, Gp, Gp) // WAITPKG
|
||||||
ASMJIT_INST_1x(umonitor, Umonitor, Mem)
|
ASMJIT_INST_1x(umonitor, Umonitor, Mem) // WAITPKG
|
||||||
ASMJIT_INST_3x(umwait, Umwait, Gp, Gp, Gp)
|
ASMJIT_INST_3x(umwait, Umwait, Gp, Gp, Gp) // WAITPKG
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
@@ -1089,36 +1102,58 @@ public:
|
|||||||
//! \name TSXLDTRK Instructions
|
//! \name TSXLDTRK Instructions
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
ASMJIT_INST_0x(xresldtrk, Xresldtrk)
|
ASMJIT_INST_0x(xresldtrk, Xresldtrk) // TSXLDTRK
|
||||||
ASMJIT_INST_0x(xsusldtrk, Xsusldtrk)
|
ASMJIT_INST_0x(xsusldtrk, Xsusldtrk) // TSXLDTRK
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
//! \name CET-IBT Instructions
|
//! \name CET-IBT Instructions
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
ASMJIT_INST_0x(endbr32, Endbr32)
|
ASMJIT_INST_0x(endbr32, Endbr32) // CET_IBT
|
||||||
ASMJIT_INST_0x(endbr64, Endbr64)
|
ASMJIT_INST_0x(endbr64, Endbr64) // CET_IBT
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
//! \name CET-SS Instructions
|
//! \name CET-SS Instructions
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
ASMJIT_INST_1x(clrssbsy, Clrssbsy, Mem)
|
ASMJIT_INST_1x(clrssbsy, Clrssbsy, Mem) // CET_SS
|
||||||
ASMJIT_INST_0x(setssbsy, Setssbsy)
|
ASMJIT_INST_0x(setssbsy, Setssbsy) // CET_SS
|
||||||
|
|
||||||
ASMJIT_INST_1x(rstorssp, Rstorssp, Mem)
|
ASMJIT_INST_1x(rstorssp, Rstorssp, Mem) // CET_SS
|
||||||
ASMJIT_INST_0x(saveprevssp, Saveprevssp)
|
ASMJIT_INST_0x(saveprevssp, Saveprevssp) // CET_SS
|
||||||
|
|
||||||
ASMJIT_INST_1x(incsspd, Incsspd, Gp)
|
ASMJIT_INST_1x(incsspd, Incsspd, Gp) // CET_SS
|
||||||
ASMJIT_INST_1x(incsspq, Incsspq, Gp)
|
ASMJIT_INST_1x(incsspq, Incsspq, Gp) // CET_SS
|
||||||
ASMJIT_INST_1x(rdsspd, Rdsspd, Gp)
|
ASMJIT_INST_1x(rdsspd, Rdsspd, Gp) // CET_SS
|
||||||
ASMJIT_INST_1x(rdsspq, Rdsspq, Gp)
|
ASMJIT_INST_1x(rdsspq, Rdsspq, Gp) // CET_SS
|
||||||
ASMJIT_INST_2x(wrssd, Wrssd, Mem, Gp)
|
ASMJIT_INST_2x(wrssd, Wrssd, Gp, Gp) // CET_SS
|
||||||
ASMJIT_INST_2x(wrssq, Wrssq, Mem, Gp)
|
ASMJIT_INST_2x(wrssd, Wrssd, Mem, Gp) // CET_SS
|
||||||
ASMJIT_INST_2x(wrussd, Wrussd, Mem, Gp)
|
ASMJIT_INST_2x(wrssq, Wrssq, Gp, Gp) // CET_SS
|
||||||
ASMJIT_INST_2x(wrussq, Wrussq, Mem, Gp)
|
ASMJIT_INST_2x(wrssq, Wrssq, Mem, Gp) // CET_SS
|
||||||
|
ASMJIT_INST_2x(wrussd, Wrussd, Gp, Gp) // CET_SS
|
||||||
|
ASMJIT_INST_2x(wrussd, Wrussd, Mem, Gp) // CET_SS
|
||||||
|
ASMJIT_INST_2x(wrussq, Wrussq, Gp, Gp) // CET_SS
|
||||||
|
ASMJIT_INST_2x(wrussq, Wrussq, Mem, Gp) // CET_SS
|
||||||
|
|
||||||
|
//! \}
|
||||||
|
|
||||||
|
//! \name HRESET Instructions
|
||||||
|
//! \{
|
||||||
|
|
||||||
|
ASMJIT_INST_2x(hreset, Hreset, Imm, Gp) // HRESET
|
||||||
|
|
||||||
|
//! \}
|
||||||
|
|
||||||
|
//! \name UINTR Instructions
|
||||||
|
//! \{
|
||||||
|
|
||||||
|
ASMJIT_INST_0x(clui, Clui) // UINTR
|
||||||
|
ASMJIT_INST_1x(senduipi, Senduipi, Gp) // UINTR
|
||||||
|
ASMJIT_INST_0x(testui, Testui) // UINTR
|
||||||
|
ASMJIT_INST_0x(stui, Stui) // UINTR
|
||||||
|
ASMJIT_INST_0x(uiret, Uiret) // UINTR
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
@@ -1193,9 +1228,11 @@ public:
|
|||||||
ASMJIT_INST_0x(vmlaunch, Vmlaunch) // VMX
|
ASMJIT_INST_0x(vmlaunch, Vmlaunch) // VMX
|
||||||
ASMJIT_INST_1x(vmptrld, Vmptrld, Mem) // VMX
|
ASMJIT_INST_1x(vmptrld, Vmptrld, Mem) // VMX
|
||||||
ASMJIT_INST_1x(vmptrst, Vmptrst, Mem) // VMX
|
ASMJIT_INST_1x(vmptrst, Vmptrst, Mem) // VMX
|
||||||
|
ASMJIT_INST_2x(vmread, Vmread, Gp, Gp) // VMX
|
||||||
ASMJIT_INST_2x(vmread, Vmread, Mem, Gp) // VMX
|
ASMJIT_INST_2x(vmread, Vmread, Mem, Gp) // VMX
|
||||||
ASMJIT_INST_0x(vmresume, Vmresume) // VMX
|
ASMJIT_INST_0x(vmresume, Vmresume) // VMX
|
||||||
ASMJIT_INST_2x(vmwrite, Vmwrite, Gp, Mem) // VMX
|
ASMJIT_INST_2x(vmwrite, Vmwrite, Gp, Mem) // VMX
|
||||||
|
ASMJIT_INST_2x(vmwrite, Vmwrite, Gp, Gp) // VMX
|
||||||
ASMJIT_INST_1x(vmxon, Vmxon, Mem) // VMX
|
ASMJIT_INST_1x(vmxon, Vmxon, Mem) // VMX
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
@@ -2238,18 +2275,10 @@ public:
|
|||||||
ASMJIT_INST_3x(vandpd, Vandpd, Vec, Vec, Mem) // AVX AVX512_DQ{kz|b64}
|
ASMJIT_INST_3x(vandpd, Vandpd, Vec, Vec, Mem) // AVX AVX512_DQ{kz|b64}
|
||||||
ASMJIT_INST_3x(vandps, Vandps, Vec, Vec, Vec) // AVX AVX512_DQ{kz|b32}
|
ASMJIT_INST_3x(vandps, Vandps, Vec, Vec, Vec) // AVX AVX512_DQ{kz|b32}
|
||||||
ASMJIT_INST_3x(vandps, Vandps, Vec, Vec, Mem) // AVX AVX512_DQ{kz|b32}
|
ASMJIT_INST_3x(vandps, Vandps, Vec, Vec, Mem) // AVX AVX512_DQ{kz|b32}
|
||||||
ASMJIT_INST_3x(vblendmb, Vblendmb, Vec, Vec, Vec) // AVX512_BW{kz}
|
|
||||||
ASMJIT_INST_3x(vblendmb, Vblendmb, Vec, Vec, Mem) // AVX512_BW{kz}
|
|
||||||
ASMJIT_INST_3x(vblendmd, Vblendmd, Vec, Vec, Vec) // AVX512_F{kz|b32}
|
|
||||||
ASMJIT_INST_3x(vblendmd, Vblendmd, Vec, Vec, Mem) // AVX512_F{kz|b32}
|
|
||||||
ASMJIT_INST_3x(vblendmpd, Vblendmpd, Vec, Vec, Vec) // AVX512_F{kz|b64}
|
ASMJIT_INST_3x(vblendmpd, Vblendmpd, Vec, Vec, Vec) // AVX512_F{kz|b64}
|
||||||
ASMJIT_INST_3x(vblendmpd, Vblendmpd, Vec, Vec, Mem) // AVX512_F{kz|b64}
|
ASMJIT_INST_3x(vblendmpd, Vblendmpd, Vec, Vec, Mem) // AVX512_F{kz|b64}
|
||||||
ASMJIT_INST_3x(vblendmps, Vblendmps, Vec, Vec, Vec) // AVX512_F{kz|b32}
|
ASMJIT_INST_3x(vblendmps, Vblendmps, Vec, Vec, Vec) // AVX512_F{kz|b32}
|
||||||
ASMJIT_INST_3x(vblendmps, Vblendmps, Vec, Vec, Mem) // AVX512_F{kz|b32}
|
ASMJIT_INST_3x(vblendmps, Vblendmps, Vec, Vec, Mem) // AVX512_F{kz|b32}
|
||||||
ASMJIT_INST_3x(vblendmq, Vblendmq, Vec, Vec, Vec) // AVX512_F{kz|b64}
|
|
||||||
ASMJIT_INST_3x(vblendmq, Vblendmq, Vec, Vec, Mem) // AVX512_F{kz|b64}
|
|
||||||
ASMJIT_INST_3x(vblendmw, Vblendmw, Vec, Vec, Vec) // AVX512_BW{kz}
|
|
||||||
ASMJIT_INST_3x(vblendmw, Vblendmw, Vec, Vec, Mem) // AVX512_BW{kz}
|
|
||||||
ASMJIT_INST_4x(vblendpd, Vblendpd, Vec, Vec, Vec, Imm) // AVX
|
ASMJIT_INST_4x(vblendpd, Vblendpd, Vec, Vec, Vec, Imm) // AVX
|
||||||
ASMJIT_INST_4x(vblendpd, Vblendpd, Vec, Vec, Mem, Imm) // AVX
|
ASMJIT_INST_4x(vblendpd, Vblendpd, Vec, Vec, Mem, Imm) // AVX
|
||||||
ASMJIT_INST_4x(vblendps, Vblendps, Vec, Vec, Vec, Imm) // AVX
|
ASMJIT_INST_4x(vblendps, Vblendps, Vec, Vec, Vec, Imm) // AVX
|
||||||
@@ -2808,6 +2837,14 @@ public:
|
|||||||
ASMJIT_INST_3x(vpavgw, Vpavgw, Vec, Vec, Mem) // AVX+ AVX512_BW{kz}
|
ASMJIT_INST_3x(vpavgw, Vpavgw, Vec, Vec, Mem) // AVX+ AVX512_BW{kz}
|
||||||
ASMJIT_INST_4x(vpblendd, Vpblendd, Vec, Vec, Vec, Imm) // AVX2
|
ASMJIT_INST_4x(vpblendd, Vpblendd, Vec, Vec, Vec, Imm) // AVX2
|
||||||
ASMJIT_INST_4x(vpblendd, Vpblendd, Vec, Vec, Mem, Imm) // AVX2
|
ASMJIT_INST_4x(vpblendd, Vpblendd, Vec, Vec, Mem, Imm) // AVX2
|
||||||
|
ASMJIT_INST_3x(vpblendmb, Vpblendmb, Vec, Vec, Vec) // AVX512_BW{kz}
|
||||||
|
ASMJIT_INST_3x(vpblendmb, Vpblendmb, Vec, Vec, Mem) // AVX512_BW{kz}
|
||||||
|
ASMJIT_INST_3x(vpblendmd, Vpblendmd, Vec, Vec, Vec) // AVX512_F{kz|b32}
|
||||||
|
ASMJIT_INST_3x(vpblendmd, Vpblendmd, Vec, Vec, Mem) // AVX512_F{kz|b32}
|
||||||
|
ASMJIT_INST_3x(vpblendmq, Vpblendmq, Vec, Vec, Vec) // AVX512_F{kz|b64}
|
||||||
|
ASMJIT_INST_3x(vpblendmq, Vpblendmq, Vec, Vec, Mem) // AVX512_F{kz|b64}
|
||||||
|
ASMJIT_INST_3x(vpblendmw, Vpblendmw, Vec, Vec, Vec) // AVX512_BW{kz}
|
||||||
|
ASMJIT_INST_3x(vpblendmw, Vpblendmw, Vec, Vec, Mem) // AVX512_BW{kz}
|
||||||
ASMJIT_INST_4x(vpblendvb, Vpblendvb, Vec, Vec, Vec, Vec) // AVX+
|
ASMJIT_INST_4x(vpblendvb, Vpblendvb, Vec, Vec, Vec, Vec) // AVX+
|
||||||
ASMJIT_INST_4x(vpblendvb, Vpblendvb, Vec, Vec, Mem, Vec) // AVX+
|
ASMJIT_INST_4x(vpblendvb, Vpblendvb, Vec, Vec, Mem, Vec) // AVX+
|
||||||
ASMJIT_INST_4x(vpblendw, Vpblendw, Vec, Vec, Vec, Imm) // AVX+
|
ASMJIT_INST_4x(vpblendw, Vpblendw, Vec, Vec, Vec, Imm) // AVX+
|
||||||
@@ -2818,8 +2855,8 @@ public:
|
|||||||
ASMJIT_INST_2x(vpbroadcastd, Vpbroadcastd, Vec, Vec) // AVX2 AVX512_F{kz}
|
ASMJIT_INST_2x(vpbroadcastd, Vpbroadcastd, Vec, Vec) // AVX2 AVX512_F{kz}
|
||||||
ASMJIT_INST_2x(vpbroadcastd, Vpbroadcastd, Vec, Mem) // AVX2 AVX512_F{kz}
|
ASMJIT_INST_2x(vpbroadcastd, Vpbroadcastd, Vec, Mem) // AVX2 AVX512_F{kz}
|
||||||
ASMJIT_INST_2x(vpbroadcastd, Vpbroadcastd, Vec, Gp) // AVX512_F{kz}
|
ASMJIT_INST_2x(vpbroadcastd, Vpbroadcastd, Vec, Gp) // AVX512_F{kz}
|
||||||
ASMJIT_INST_2x(vpbroadcastmb2d, Vpbroadcastmb2d, Vec, KReg) // AVX512_CD
|
|
||||||
ASMJIT_INST_2x(vpbroadcastmb2q, Vpbroadcastmb2q, Vec, KReg) // AVX512_CD
|
ASMJIT_INST_2x(vpbroadcastmb2q, Vpbroadcastmb2q, Vec, KReg) // AVX512_CD
|
||||||
|
ASMJIT_INST_2x(vpbroadcastmw2d, Vpbroadcastmw2d, Vec, KReg) // AVX512_CD
|
||||||
ASMJIT_INST_2x(vpbroadcastq, Vpbroadcastq, Vec, Vec) // AVX2 AVX512_F{kz}
|
ASMJIT_INST_2x(vpbroadcastq, Vpbroadcastq, Vec, Vec) // AVX2 AVX512_F{kz}
|
||||||
ASMJIT_INST_2x(vpbroadcastq, Vpbroadcastq, Vec, Mem) // AVX2 AVX512_F{kz}
|
ASMJIT_INST_2x(vpbroadcastq, Vpbroadcastq, Vec, Mem) // AVX2 AVX512_F{kz}
|
||||||
ASMJIT_INST_2x(vpbroadcastq, Vpbroadcastq, Vec, Gp) // AVX512_F{kz}
|
ASMJIT_INST_2x(vpbroadcastq, Vpbroadcastq, Vec, Gp) // AVX512_F{kz}
|
||||||
@@ -3175,14 +3212,20 @@ public:
|
|||||||
ASMJIT_INST_2x(vpscatterqq, Vpscatterqq, Mem, Vec) // AVX512_F{k}
|
ASMJIT_INST_2x(vpscatterqq, Vpscatterqq, Mem, Vec) // AVX512_F{k}
|
||||||
ASMJIT_INST_4x(vpshldd, Vpshldd, Vec, Vec, Vec, Imm) // AVX512_VBMI2{kz}
|
ASMJIT_INST_4x(vpshldd, Vpshldd, Vec, Vec, Vec, Imm) // AVX512_VBMI2{kz}
|
||||||
ASMJIT_INST_4x(vpshldd, Vpshldd, Vec, Vec, Mem, Imm) // AVX512_VBMI2{kz}
|
ASMJIT_INST_4x(vpshldd, Vpshldd, Vec, Vec, Mem, Imm) // AVX512_VBMI2{kz}
|
||||||
|
ASMJIT_INST_4x(vpshldq, Vpshldq, Vec, Vec, Vec, Imm) // AVX512_VBMI2{kz}
|
||||||
|
ASMJIT_INST_4x(vpshldq, Vpshldq, Vec, Vec, Mem, Imm) // AVX512_VBMI2{kz}
|
||||||
ASMJIT_INST_3x(vpshldvd, Vpshldvd, Vec, Vec, Vec) // AVX512_VBMI2{kz}
|
ASMJIT_INST_3x(vpshldvd, Vpshldvd, Vec, Vec, Vec) // AVX512_VBMI2{kz}
|
||||||
ASMJIT_INST_3x(vpshldvd, Vpshldvd, Vec, Vec, Mem) // AVX512_VBMI2{kz}
|
ASMJIT_INST_3x(vpshldvd, Vpshldvd, Vec, Vec, Mem) // AVX512_VBMI2{kz}
|
||||||
ASMJIT_INST_3x(vpshldvq, Vpshldvq, Vec, Vec, Vec) // AVX512_VBMI2{kz}
|
ASMJIT_INST_3x(vpshldvq, Vpshldvq, Vec, Vec, Vec) // AVX512_VBMI2{kz}
|
||||||
ASMJIT_INST_3x(vpshldvq, Vpshldvq, Vec, Vec, Mem) // AVX512_VBMI2{kz}
|
ASMJIT_INST_3x(vpshldvq, Vpshldvq, Vec, Vec, Mem) // AVX512_VBMI2{kz}
|
||||||
ASMJIT_INST_3x(vpshldvw, Vpshldvw, Vec, Vec, Vec) // AVX512_VBMI2{kz}
|
ASMJIT_INST_3x(vpshldvw, Vpshldvw, Vec, Vec, Vec) // AVX512_VBMI2{kz}
|
||||||
ASMJIT_INST_3x(vpshldvw, Vpshldvw, Vec, Vec, Mem) // AVX512_VBMI2{kz}
|
ASMJIT_INST_3x(vpshldvw, Vpshldvw, Vec, Vec, Mem) // AVX512_VBMI2{kz}
|
||||||
|
ASMJIT_INST_4x(vpshldw, Vpshldw, Vec, Vec, Vec, Imm) // AVX512_VBMI2{kz}
|
||||||
|
ASMJIT_INST_4x(vpshldw, Vpshldw, Vec, Vec, Mem, Imm) // AVX512_VBMI2{kz}
|
||||||
ASMJIT_INST_4x(vpshrdd, Vpshrdd, Vec, Vec, Vec, Imm) // AVX512_VBMI2{kz}
|
ASMJIT_INST_4x(vpshrdd, Vpshrdd, Vec, Vec, Vec, Imm) // AVX512_VBMI2{kz}
|
||||||
ASMJIT_INST_4x(vpshrdd, Vpshrdd, Vec, Vec, Mem, Imm) // AVX512_VBMI2{kz}
|
ASMJIT_INST_4x(vpshrdd, Vpshrdd, Vec, Vec, Mem, Imm) // AVX512_VBMI2{kz}
|
||||||
|
ASMJIT_INST_4x(vpshrdq, Vpshrdq, Vec, Vec, Vec, Imm) // AVX512_VBMI2{kz}
|
||||||
|
ASMJIT_INST_4x(vpshrdq, Vpshrdq, Vec, Vec, Mem, Imm) // AVX512_VBMI2{kz}
|
||||||
ASMJIT_INST_3x(vpshrdvd, Vpshrdvd, Vec, Vec, Vec) // AVX512_VBMI2{kz}
|
ASMJIT_INST_3x(vpshrdvd, Vpshrdvd, Vec, Vec, Vec) // AVX512_VBMI2{kz}
|
||||||
ASMJIT_INST_3x(vpshrdvd, Vpshrdvd, Vec, Vec, Mem) // AVX512_VBMI2{kz}
|
ASMJIT_INST_3x(vpshrdvd, Vpshrdvd, Vec, Vec, Mem) // AVX512_VBMI2{kz}
|
||||||
ASMJIT_INST_3x(vpshrdvq, Vpshrdvq, Vec, Vec, Vec) // AVX512_VBMI2{kz}
|
ASMJIT_INST_3x(vpshrdvq, Vpshrdvq, Vec, Vec, Vec) // AVX512_VBMI2{kz}
|
||||||
@@ -3768,7 +3811,6 @@ struct EmitterImplicitT : public EmitterExplicitT<This> {
|
|||||||
ASMJIT_INST_0x(iret, Iret) // ANY [IMPLICIT]
|
ASMJIT_INST_0x(iret, Iret) // ANY [IMPLICIT]
|
||||||
ASMJIT_INST_0x(iretd, Iretd) // ANY [IMPLICIT]
|
ASMJIT_INST_0x(iretd, Iretd) // ANY [IMPLICIT]
|
||||||
ASMJIT_INST_0x(iretq, Iretq) // X64 [IMPLICIT]
|
ASMJIT_INST_0x(iretq, Iretq) // X64 [IMPLICIT]
|
||||||
ASMJIT_INST_0x(iretw, Iretw) // ANY [IMPLICIT]
|
|
||||||
ASMJIT_INST_1x(jecxz, Jecxz, Label) // ANY [IMPLICIT] Short jump if CX/ECX/RCX is zero.
|
ASMJIT_INST_1x(jecxz, Jecxz, Label) // ANY [IMPLICIT] Short jump if CX/ECX/RCX is zero.
|
||||||
ASMJIT_INST_1x(jecxz, Jecxz, Imm) // ANY [IMPLICIT] Short jump if CX/ECX/RCX is zero.
|
ASMJIT_INST_1x(jecxz, Jecxz, Imm) // ANY [IMPLICIT] Short jump if CX/ECX/RCX is zero.
|
||||||
ASMJIT_INST_1x(loop, Loop, Label) // ANY [IMPLICIT] Decrement xCX; short jump if xCX != 0.
|
ASMJIT_INST_1x(loop, Loop, Label) // ANY [IMPLICIT] Decrement xCX; short jump if xCX != 0.
|
||||||
@@ -3781,8 +3823,8 @@ struct EmitterImplicitT : public EmitterExplicitT<This> {
|
|||||||
ASMJIT_INST_1x(mul, Mul, Mem) // ANY [IMPLICIT] {AX <- AL * m8} {xDX:xAX <- xAX * m16|m32|m64}
|
ASMJIT_INST_1x(mul, Mul, Mem) // ANY [IMPLICIT] {AX <- AL * m8} {xDX:xAX <- xAX * m16|m32|m64}
|
||||||
ASMJIT_INST_0x(ret, Ret)
|
ASMJIT_INST_0x(ret, Ret)
|
||||||
ASMJIT_INST_1x(ret, Ret, Imm)
|
ASMJIT_INST_1x(ret, Ret, Imm)
|
||||||
ASMJIT_INST_0x(lret, Lret)
|
ASMJIT_INST_0x(retf, Retf)
|
||||||
ASMJIT_INST_1x(lret, Lret, Imm)
|
ASMJIT_INST_1x(retf, Retf, Imm)
|
||||||
ASMJIT_INST_0x(xlatb, Xlatb) // ANY [IMPLICIT]
|
ASMJIT_INST_0x(xlatb, Xlatb) // ANY [IMPLICIT]
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
@@ -3918,10 +3960,20 @@ struct EmitterImplicitT : public EmitterExplicitT<This> {
|
|||||||
//! \name XSAVE Instructions
|
//! \name XSAVE Instructions
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
// TODO: xrstor and xsave don't have explicit variants yet.
|
|
||||||
|
|
||||||
//! \cond
|
//! \cond
|
||||||
using EmitterExplicitT<This>::xgetbv;
|
using EmitterExplicitT<This>::xgetbv;
|
||||||
|
using EmitterExplicitT<This>::xrstor;
|
||||||
|
using EmitterExplicitT<This>::xrstor64;
|
||||||
|
using EmitterExplicitT<This>::xrstors;
|
||||||
|
using EmitterExplicitT<This>::xrstors64;
|
||||||
|
using EmitterExplicitT<This>::xsave;
|
||||||
|
using EmitterExplicitT<This>::xsave64;
|
||||||
|
using EmitterExplicitT<This>::xsavec;
|
||||||
|
using EmitterExplicitT<This>::xsavec64;
|
||||||
|
using EmitterExplicitT<This>::xsaveopt;
|
||||||
|
using EmitterExplicitT<This>::xsaveopt64;
|
||||||
|
using EmitterExplicitT<This>::xsaves;
|
||||||
|
using EmitterExplicitT<This>::xsaves64;
|
||||||
//! \endcond
|
//! \endcond
|
||||||
|
|
||||||
ASMJIT_INST_0x(xgetbv, Xgetbv) // XSAVE [IMPLICIT] EDX:EAX <- XCR[ECX]
|
ASMJIT_INST_0x(xgetbv, Xgetbv) // XSAVE [IMPLICIT] EDX:EAX <- XCR[ECX]
|
||||||
@@ -3948,6 +4000,17 @@ struct EmitterImplicitT : public EmitterExplicitT<This> {
|
|||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
|
//! \name HRESET Instructions
|
||||||
|
//! \{
|
||||||
|
|
||||||
|
//! \cond
|
||||||
|
using EmitterExplicitT<This>::hreset;
|
||||||
|
//! \endcond
|
||||||
|
|
||||||
|
ASMJIT_INST_1x(hreset, Hreset, Imm) // HRESET [IMPLICIT]
|
||||||
|
|
||||||
|
//! \}
|
||||||
|
|
||||||
//! \name Privileged Instructions
|
//! \name Privileged Instructions
|
||||||
//! \{
|
//! \{
|
||||||
|
|
||||||
@@ -3962,9 +4025,9 @@ struct EmitterImplicitT : public EmitterExplicitT<This> {
|
|||||||
ASMJIT_INST_0x(rdmsr, Rdmsr) // ANY [IMPLICIT]
|
ASMJIT_INST_0x(rdmsr, Rdmsr) // ANY [IMPLICIT]
|
||||||
ASMJIT_INST_0x(rdpmc, Rdpmc) // ANY [IMPLICIT]
|
ASMJIT_INST_0x(rdpmc, Rdpmc) // ANY [IMPLICIT]
|
||||||
ASMJIT_INST_0x(sysexit, Sysexit) // X64 [IMPLICIT]
|
ASMJIT_INST_0x(sysexit, Sysexit) // X64 [IMPLICIT]
|
||||||
ASMJIT_INST_0x(sysexit64, Sysexit64) // X64 [IMPLICIT]
|
ASMJIT_INST_0x(sysexitq, Sysexitq) // X64 [IMPLICIT]
|
||||||
ASMJIT_INST_0x(sysret, Sysret) // X64 [IMPLICIT]
|
ASMJIT_INST_0x(sysret, Sysret) // X64 [IMPLICIT]
|
||||||
ASMJIT_INST_0x(sysret64, Sysret64) // X64 [IMPLICIT]
|
ASMJIT_INST_0x(sysretq, Sysretq) // X64 [IMPLICIT]
|
||||||
ASMJIT_INST_0x(wrmsr, Wrmsr) // ANY [IMPLICIT]
|
ASMJIT_INST_0x(wrmsr, Wrmsr) // ANY [IMPLICIT]
|
||||||
ASMJIT_INST_0x(xsetbv, Xsetbv) // XSAVE [IMPLICIT] XCR[ECX] <- EDX:EAX
|
ASMJIT_INST_0x(xsetbv, Xsetbv) // XSAVE [IMPLICIT] XCR[ECX] <- EDX:EAX
|
||||||
|
|
||||||
|
|||||||
@@ -188,15 +188,15 @@ static const RegFormatInfo x86RegFormatInfo = {
|
|||||||
|
|
||||||
static const char* x86GetAddressSizeString(uint32_t size) noexcept {
|
static const char* x86GetAddressSizeString(uint32_t size) noexcept {
|
||||||
switch (size) {
|
switch (size) {
|
||||||
case 1 : return "byte ";
|
case 1 : return "byte ptr ";
|
||||||
case 2 : return "word ";
|
case 2 : return "word ptr ";
|
||||||
case 4 : return "dword ";
|
case 4 : return "dword ptr ";
|
||||||
case 6 : return "fword ";
|
case 6 : return "fword ptr ";
|
||||||
case 8 : return "qword ";
|
case 8 : return "qword ptr ";
|
||||||
case 10: return "tbyte ";
|
case 10: return "tbyte ptr ";
|
||||||
case 16: return "oword ";
|
case 16: return "xmmword ptr ";
|
||||||
case 32: return "yword ";
|
case 32: return "ymmword ptr ";
|
||||||
case 64: return "zword ";
|
case 64: return "zmmword ptr ";
|
||||||
default: return "";
|
default: return "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -835,6 +835,17 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction(
|
|||||||
|
|
||||||
// Format instruction options and instruction mnemonic.
|
// Format instruction options and instruction mnemonic.
|
||||||
if (instId < Inst::_kIdCount) {
|
if (instId < Inst::_kIdCount) {
|
||||||
|
// VEX|EVEX options.
|
||||||
|
if (options & Inst::kOptionVex) ASMJIT_PROPAGATE(sb.append("{vex} "));
|
||||||
|
if (options & Inst::kOptionVex3) ASMJIT_PROPAGATE(sb.append("{vex3} "));
|
||||||
|
if (options & Inst::kOptionEvex) ASMJIT_PROPAGATE(sb.append("{evex} "));
|
||||||
|
|
||||||
|
// MOD/RM and MOD/MR options
|
||||||
|
if (options & Inst::kOptionModRM)
|
||||||
|
ASMJIT_PROPAGATE(sb.append("{modrm} "));
|
||||||
|
else if (options & Inst::kOptionModMR)
|
||||||
|
ASMJIT_PROPAGATE(sb.append("{modmr} "));
|
||||||
|
|
||||||
// SHORT|LONG options.
|
// SHORT|LONG options.
|
||||||
if (options & Inst::kOptionShortForm) ASMJIT_PROPAGATE(sb.append("short "));
|
if (options & Inst::kOptionShortForm) ASMJIT_PROPAGATE(sb.append("short "));
|
||||||
if (options & Inst::kOptionLongForm) ASMJIT_PROPAGATE(sb.append("long "));
|
if (options & Inst::kOptionLongForm) ASMJIT_PROPAGATE(sb.append("long "));
|
||||||
@@ -873,11 +884,6 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// VEX|EVEX options.
|
|
||||||
if (options & Inst::kOptionVex) ASMJIT_PROPAGATE(sb.append("{vex} "));
|
|
||||||
if (options & Inst::kOptionVex3) ASMJIT_PROPAGATE(sb.append("{vex3} "));
|
|
||||||
if (options & Inst::kOptionEvex) ASMJIT_PROPAGATE(sb.append("{evex} "));
|
|
||||||
|
|
||||||
ASMJIT_PROPAGATE(InstAPI::instIdToString(arch, instId, sb));
|
ASMJIT_PROPAGATE(InstAPI::instIdToString(arch, instId, sb));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdCli, //!< Instruction 'cli'.
|
kIdCli, //!< Instruction 'cli'.
|
||||||
kIdClrssbsy, //!< Instruction 'clrssbsy' {CET_SS}.
|
kIdClrssbsy, //!< Instruction 'clrssbsy' {CET_SS}.
|
||||||
kIdClts, //!< Instruction 'clts'.
|
kIdClts, //!< Instruction 'clts'.
|
||||||
|
kIdClui, //!< Instruction 'clui' {UINTR} (X64).
|
||||||
kIdClwb, //!< Instruction 'clwb' {CLWB}.
|
kIdClwb, //!< Instruction 'clwb' {CLWB}.
|
||||||
kIdClzero, //!< Instruction 'clzero' {CLZERO}.
|
kIdClzero, //!< Instruction 'clzero' {CLZERO}.
|
||||||
kIdCmc, //!< Instruction 'cmc'.
|
kIdCmc, //!< Instruction 'cmc'.
|
||||||
@@ -315,6 +316,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdHaddpd, //!< Instruction 'haddpd' {SSE3}.
|
kIdHaddpd, //!< Instruction 'haddpd' {SSE3}.
|
||||||
kIdHaddps, //!< Instruction 'haddps' {SSE3}.
|
kIdHaddps, //!< Instruction 'haddps' {SSE3}.
|
||||||
kIdHlt, //!< Instruction 'hlt'.
|
kIdHlt, //!< Instruction 'hlt'.
|
||||||
|
kIdHreset, //!< Instruction 'hreset' {HRESET}.
|
||||||
kIdHsubpd, //!< Instruction 'hsubpd' {SSE3}.
|
kIdHsubpd, //!< Instruction 'hsubpd' {SSE3}.
|
||||||
kIdHsubps, //!< Instruction 'hsubps' {SSE3}.
|
kIdHsubps, //!< Instruction 'hsubps' {SSE3}.
|
||||||
kIdIdiv, //!< Instruction 'idiv'.
|
kIdIdiv, //!< Instruction 'idiv'.
|
||||||
@@ -338,7 +340,6 @@ struct Inst : public BaseInst {
|
|||||||
kIdIret, //!< Instruction 'iret'.
|
kIdIret, //!< Instruction 'iret'.
|
||||||
kIdIretd, //!< Instruction 'iretd'.
|
kIdIretd, //!< Instruction 'iretd'.
|
||||||
kIdIretq, //!< Instruction 'iretq' (X64).
|
kIdIretq, //!< Instruction 'iretq' (X64).
|
||||||
kIdIretw, //!< Instruction 'iretw'.
|
|
||||||
kIdJa, //!< Instruction 'ja'.
|
kIdJa, //!< Instruction 'ja'.
|
||||||
kIdJae, //!< Instruction 'jae'.
|
kIdJae, //!< Instruction 'jae'.
|
||||||
kIdJb, //!< Instruction 'jb'.
|
kIdJb, //!< Instruction 'jb'.
|
||||||
@@ -445,7 +446,6 @@ struct Inst : public BaseInst {
|
|||||||
kIdLoop, //!< Instruction 'loop'.
|
kIdLoop, //!< Instruction 'loop'.
|
||||||
kIdLoope, //!< Instruction 'loope'.
|
kIdLoope, //!< Instruction 'loope'.
|
||||||
kIdLoopne, //!< Instruction 'loopne'.
|
kIdLoopne, //!< Instruction 'loopne'.
|
||||||
kIdLret, //!< Instruction 'lret'.
|
|
||||||
kIdLsl, //!< Instruction 'lsl'.
|
kIdLsl, //!< Instruction 'lsl'.
|
||||||
kIdLss, //!< Instruction 'lss'.
|
kIdLss, //!< Instruction 'lss'.
|
||||||
kIdLtr, //!< Instruction 'ltr'.
|
kIdLtr, //!< Instruction 'ltr'.
|
||||||
@@ -716,6 +716,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdRdtsc, //!< Instruction 'rdtsc' {RDTSC}.
|
kIdRdtsc, //!< Instruction 'rdtsc' {RDTSC}.
|
||||||
kIdRdtscp, //!< Instruction 'rdtscp' {RDTSCP}.
|
kIdRdtscp, //!< Instruction 'rdtscp' {RDTSCP}.
|
||||||
kIdRet, //!< Instruction 'ret'.
|
kIdRet, //!< Instruction 'ret'.
|
||||||
|
kIdRetf, //!< Instruction 'retf'.
|
||||||
kIdRmpadjust, //!< Instruction 'rmpadjust' {SNP} (X64).
|
kIdRmpadjust, //!< Instruction 'rmpadjust' {SNP} (X64).
|
||||||
kIdRmpupdate, //!< Instruction 'rmpupdate' {SNP} (X64).
|
kIdRmpupdate, //!< Instruction 'rmpupdate' {SNP} (X64).
|
||||||
kIdRol, //!< Instruction 'rol'.
|
kIdRol, //!< Instruction 'rol'.
|
||||||
@@ -736,6 +737,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdSaveprevssp, //!< Instruction 'saveprevssp' {CET_SS}.
|
kIdSaveprevssp, //!< Instruction 'saveprevssp' {CET_SS}.
|
||||||
kIdSbb, //!< Instruction 'sbb'.
|
kIdSbb, //!< Instruction 'sbb'.
|
||||||
kIdScas, //!< Instruction 'scas'.
|
kIdScas, //!< Instruction 'scas'.
|
||||||
|
kIdSenduipi, //!< Instruction 'senduipi' {UINTR} (X64).
|
||||||
kIdSerialize, //!< Instruction 'serialize' {SERIALIZE}.
|
kIdSerialize, //!< Instruction 'serialize' {SERIALIZE}.
|
||||||
kIdSeta, //!< Instruction 'seta'.
|
kIdSeta, //!< Instruction 'seta'.
|
||||||
kIdSetae, //!< Instruction 'setae'.
|
kIdSetae, //!< Instruction 'setae'.
|
||||||
@@ -803,6 +805,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdStos, //!< Instruction 'stos'.
|
kIdStos, //!< Instruction 'stos'.
|
||||||
kIdStr, //!< Instruction 'str'.
|
kIdStr, //!< Instruction 'str'.
|
||||||
kIdSttilecfg, //!< Instruction 'sttilecfg' {AMX_TILE} (X64).
|
kIdSttilecfg, //!< Instruction 'sttilecfg' {AMX_TILE} (X64).
|
||||||
|
kIdStui, //!< Instruction 'stui' {UINTR} (X64).
|
||||||
kIdSub, //!< Instruction 'sub'.
|
kIdSub, //!< Instruction 'sub'.
|
||||||
kIdSubpd, //!< Instruction 'subpd' {SSE2}.
|
kIdSubpd, //!< Instruction 'subpd' {SSE2}.
|
||||||
kIdSubps, //!< Instruction 'subps' {SSE}.
|
kIdSubps, //!< Instruction 'subps' {SSE}.
|
||||||
@@ -812,9 +815,9 @@ struct Inst : public BaseInst {
|
|||||||
kIdSyscall, //!< Instruction 'syscall' (X64).
|
kIdSyscall, //!< Instruction 'syscall' (X64).
|
||||||
kIdSysenter, //!< Instruction 'sysenter'.
|
kIdSysenter, //!< Instruction 'sysenter'.
|
||||||
kIdSysexit, //!< Instruction 'sysexit'.
|
kIdSysexit, //!< Instruction 'sysexit'.
|
||||||
kIdSysexit64, //!< Instruction 'sysexit64'.
|
kIdSysexitq, //!< Instruction 'sysexitq'.
|
||||||
kIdSysret, //!< Instruction 'sysret' (X64).
|
kIdSysret, //!< Instruction 'sysret' (X64).
|
||||||
kIdSysret64, //!< Instruction 'sysret64' (X64).
|
kIdSysretq, //!< Instruction 'sysretq' (X64).
|
||||||
kIdT1mskc, //!< Instruction 't1mskc' {TBM}.
|
kIdT1mskc, //!< Instruction 't1mskc' {TBM}.
|
||||||
kIdTdpbf16ps, //!< Instruction 'tdpbf16ps' {AMX_BF16} (X64).
|
kIdTdpbf16ps, //!< Instruction 'tdpbf16ps' {AMX_BF16} (X64).
|
||||||
kIdTdpbssd, //!< Instruction 'tdpbssd' {AMX_INT8} (X64).
|
kIdTdpbssd, //!< Instruction 'tdpbssd' {AMX_INT8} (X64).
|
||||||
@@ -822,6 +825,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdTdpbusd, //!< Instruction 'tdpbusd' {AMX_INT8} (X64).
|
kIdTdpbusd, //!< Instruction 'tdpbusd' {AMX_INT8} (X64).
|
||||||
kIdTdpbuud, //!< Instruction 'tdpbuud' {AMX_INT8} (X64).
|
kIdTdpbuud, //!< Instruction 'tdpbuud' {AMX_INT8} (X64).
|
||||||
kIdTest, //!< Instruction 'test'.
|
kIdTest, //!< Instruction 'test'.
|
||||||
|
kIdTestui, //!< Instruction 'testui' {UINTR} (X64).
|
||||||
kIdTileloadd, //!< Instruction 'tileloadd' {AMX_TILE} (X64).
|
kIdTileloadd, //!< Instruction 'tileloadd' {AMX_TILE} (X64).
|
||||||
kIdTileloaddt1, //!< Instruction 'tileloaddt1' {AMX_TILE} (X64).
|
kIdTileloaddt1, //!< Instruction 'tileloaddt1' {AMX_TILE} (X64).
|
||||||
kIdTilerelease, //!< Instruction 'tilerelease' {AMX_TILE} (X64).
|
kIdTilerelease, //!< Instruction 'tilerelease' {AMX_TILE} (X64).
|
||||||
@@ -835,6 +839,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdUd0, //!< Instruction 'ud0'.
|
kIdUd0, //!< Instruction 'ud0'.
|
||||||
kIdUd1, //!< Instruction 'ud1'.
|
kIdUd1, //!< Instruction 'ud1'.
|
||||||
kIdUd2, //!< Instruction 'ud2'.
|
kIdUd2, //!< Instruction 'ud2'.
|
||||||
|
kIdUiret, //!< Instruction 'uiret' {UINTR} (X64).
|
||||||
kIdUmonitor, //!< Instruction 'umonitor' {WAITPKG}.
|
kIdUmonitor, //!< Instruction 'umonitor' {WAITPKG}.
|
||||||
kIdUmwait, //!< Instruction 'umwait' {WAITPKG}.
|
kIdUmwait, //!< Instruction 'umwait' {WAITPKG}.
|
||||||
kIdUnpckhpd, //!< Instruction 'unpckhpd' {SSE2}.
|
kIdUnpckhpd, //!< Instruction 'unpckhpd' {SSE2}.
|
||||||
@@ -863,12 +868,8 @@ struct Inst : public BaseInst {
|
|||||||
kIdVandnps, //!< Instruction 'vandnps' {AVX|AVX512_DQ+VL}.
|
kIdVandnps, //!< Instruction 'vandnps' {AVX|AVX512_DQ+VL}.
|
||||||
kIdVandpd, //!< Instruction 'vandpd' {AVX|AVX512_DQ+VL}.
|
kIdVandpd, //!< Instruction 'vandpd' {AVX|AVX512_DQ+VL}.
|
||||||
kIdVandps, //!< Instruction 'vandps' {AVX|AVX512_DQ+VL}.
|
kIdVandps, //!< Instruction 'vandps' {AVX|AVX512_DQ+VL}.
|
||||||
kIdVblendmb, //!< Instruction 'vblendmb' {AVX512_BW+VL}.
|
|
||||||
kIdVblendmd, //!< Instruction 'vblendmd' {AVX512_F+VL}.
|
|
||||||
kIdVblendmpd, //!< Instruction 'vblendmpd' {AVX512_F+VL}.
|
kIdVblendmpd, //!< Instruction 'vblendmpd' {AVX512_F+VL}.
|
||||||
kIdVblendmps, //!< Instruction 'vblendmps' {AVX512_F+VL}.
|
kIdVblendmps, //!< Instruction 'vblendmps' {AVX512_F+VL}.
|
||||||
kIdVblendmq, //!< Instruction 'vblendmq' {AVX512_F+VL}.
|
|
||||||
kIdVblendmw, //!< Instruction 'vblendmw' {AVX512_BW+VL}.
|
|
||||||
kIdVblendpd, //!< Instruction 'vblendpd' {AVX}.
|
kIdVblendpd, //!< Instruction 'vblendpd' {AVX}.
|
||||||
kIdVblendps, //!< Instruction 'vblendps' {AVX}.
|
kIdVblendps, //!< Instruction 'vblendps' {AVX}.
|
||||||
kIdVblendvpd, //!< Instruction 'vblendvpd' {AVX}.
|
kIdVblendvpd, //!< Instruction 'vblendvpd' {AVX}.
|
||||||
@@ -1189,12 +1190,16 @@ struct Inst : public BaseInst {
|
|||||||
kIdVpavgb, //!< Instruction 'vpavgb' {AVX|AVX2|AVX512_BW+VL}.
|
kIdVpavgb, //!< Instruction 'vpavgb' {AVX|AVX2|AVX512_BW+VL}.
|
||||||
kIdVpavgw, //!< Instruction 'vpavgw' {AVX|AVX2|AVX512_BW+VL}.
|
kIdVpavgw, //!< Instruction 'vpavgw' {AVX|AVX2|AVX512_BW+VL}.
|
||||||
kIdVpblendd, //!< Instruction 'vpblendd' {AVX2}.
|
kIdVpblendd, //!< Instruction 'vpblendd' {AVX2}.
|
||||||
|
kIdVpblendmb, //!< Instruction 'vpblendmb' {AVX512_BW+VL}.
|
||||||
|
kIdVpblendmd, //!< Instruction 'vpblendmd' {AVX512_F+VL}.
|
||||||
|
kIdVpblendmq, //!< Instruction 'vpblendmq' {AVX512_F+VL}.
|
||||||
|
kIdVpblendmw, //!< Instruction 'vpblendmw' {AVX512_BW+VL}.
|
||||||
kIdVpblendvb, //!< Instruction 'vpblendvb' {AVX|AVX2}.
|
kIdVpblendvb, //!< Instruction 'vpblendvb' {AVX|AVX2}.
|
||||||
kIdVpblendw, //!< Instruction 'vpblendw' {AVX|AVX2}.
|
kIdVpblendw, //!< Instruction 'vpblendw' {AVX|AVX2}.
|
||||||
kIdVpbroadcastb, //!< Instruction 'vpbroadcastb' {AVX2|AVX512_BW+VL}.
|
kIdVpbroadcastb, //!< Instruction 'vpbroadcastb' {AVX2|AVX512_BW+VL}.
|
||||||
kIdVpbroadcastd, //!< Instruction 'vpbroadcastd' {AVX2|AVX512_F+VL}.
|
kIdVpbroadcastd, //!< Instruction 'vpbroadcastd' {AVX2|AVX512_F+VL}.
|
||||||
kIdVpbroadcastmb2d, //!< Instruction 'vpbroadcastmb2d' {AVX512_CDI+VL}.
|
|
||||||
kIdVpbroadcastmb2q, //!< Instruction 'vpbroadcastmb2q' {AVX512_CDI+VL}.
|
kIdVpbroadcastmb2q, //!< Instruction 'vpbroadcastmb2q' {AVX512_CDI+VL}.
|
||||||
|
kIdVpbroadcastmw2d, //!< Instruction 'vpbroadcastmw2d' {AVX512_CDI+VL}.
|
||||||
kIdVpbroadcastq, //!< Instruction 'vpbroadcastq' {AVX2|AVX512_F+VL}.
|
kIdVpbroadcastq, //!< Instruction 'vpbroadcastq' {AVX2|AVX512_F+VL}.
|
||||||
kIdVpbroadcastw, //!< Instruction 'vpbroadcastw' {AVX2|AVX512_BW+VL}.
|
kIdVpbroadcastw, //!< Instruction 'vpbroadcastw' {AVX2|AVX512_BW+VL}.
|
||||||
kIdVpclmulqdq, //!< Instruction 'vpclmulqdq' {AVX|AVX512_F+VL & PCLMULQDQ|VPCLMULQDQ}.
|
kIdVpclmulqdq, //!< Instruction 'vpclmulqdq' {AVX|AVX512_F+VL & PCLMULQDQ|VPCLMULQDQ}.
|
||||||
@@ -1606,7 +1611,8 @@ struct Inst : public BaseInst {
|
|||||||
|
|
||||||
//! Instruction options.
|
//! Instruction options.
|
||||||
enum Options : uint32_t {
|
enum Options : uint32_t {
|
||||||
kOptionModMR = 0x00000100u, //!< Use ModMR instead of ModRM when it's available.
|
kOptionModMR = 0x00000100u, //!< Use ModMR instead of ModRM if applicable.
|
||||||
|
kOptionModRM = 0x00000200u, //!< Use ModRM instead of ModMR if applicable.
|
||||||
kOptionVex3 = 0x00000400u, //!< Use 3-byte VEX prefix if possible (AVX) (must be 0x00000400).
|
kOptionVex3 = 0x00000400u, //!< Use 3-byte VEX prefix if possible (AVX) (must be 0x00000400).
|
||||||
kOptionVex = 0x00000800u, //!< Use VEX prefix when both VEX|EVEX prefixes are available (HINT: AVX_VNNI).
|
kOptionVex = 0x00000800u, //!< Use VEX prefix when both VEX|EVEX prefixes are available (HINT: AVX_VNNI).
|
||||||
kOptionEvex = 0x00001000u, //!< Use 4-byte EVEX prefix if possible (AVX-512) (must be 0x00001000).
|
kOptionEvex = 0x00001000u, //!< Use 4-byte EVEX prefix if possible (AVX-512) (must be 0x00001000).
|
||||||
|
|||||||
@@ -1180,6 +1180,46 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case InstDB::RWInfo::kCategoryPunpcklxx: {
|
||||||
|
// Special case for 'punpcklbw|punpckldq|punpcklwd' instructions.
|
||||||
|
if (opCount == 2) {
|
||||||
|
if (Reg::isXmm(operands[0])) {
|
||||||
|
out->_operands[0].reset(X, 16);
|
||||||
|
out->_operands[0].setReadByteMask(0x0F0Fu);
|
||||||
|
out->_operands[0].setWriteByteMask(0xFFFFu);
|
||||||
|
out->_operands[1].reset(R, 16);
|
||||||
|
out->_operands[1].setWriteByteMask(0x0F0Fu);
|
||||||
|
|
||||||
|
if (Reg::isXmm(operands[1])) {
|
||||||
|
return kErrorOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operands[1].isMem()) {
|
||||||
|
out->_operands[1].addOpFlags(MibRead);
|
||||||
|
return kErrorOk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Reg::isMm(operands[0])) {
|
||||||
|
out->_operands[0].reset(X, 8);
|
||||||
|
out->_operands[0].setReadByteMask(0x0Fu);
|
||||||
|
out->_operands[0].setWriteByteMask(0xFFu);
|
||||||
|
out->_operands[1].reset(R, 4);
|
||||||
|
out->_operands[1].setReadByteMask(0x0Fu);
|
||||||
|
|
||||||
|
if (Reg::isMm(operands[1])) {
|
||||||
|
return kErrorOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operands[1].isMem()) {
|
||||||
|
out->_operands[1].addOpFlags(MibRead);
|
||||||
|
return kErrorOk;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case InstDB::RWInfo::kCategoryVmaskmov: {
|
case InstDB::RWInfo::kCategoryVmaskmov: {
|
||||||
// Special case for 'vmaskmovpd|vmaskmovps|vpmaskmovd|vpmaskmovq' instructions.
|
// Special case for 'vmaskmovpd|vmaskmovps|vpmaskmovd|vpmaskmovq' instructions.
|
||||||
if (opCount == 3) {
|
if (opCount == 3) {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -56,10 +56,12 @@ enum EncodingId : uint32_t {
|
|||||||
kEncodingX86Op_MemZAX, //!< X86 [OP] (implicit or explicit '[EAX|RAX]' form).
|
kEncodingX86Op_MemZAX, //!< X86 [OP] (implicit or explicit '[EAX|RAX]' form).
|
||||||
kEncodingX86I_xAX, //!< X86 [I] (implicit or explicit '?AX' form).
|
kEncodingX86I_xAX, //!< X86 [I] (implicit or explicit '?AX' form).
|
||||||
kEncodingX86M, //!< X86 [M] (handles 2|4|8-bytes size).
|
kEncodingX86M, //!< X86 [M] (handles 2|4|8-bytes size).
|
||||||
|
kEncodingX86M_NoMemSize, //!< X86 [M] (handles 2|4|8-bytes size, but doesn't consider memory size).
|
||||||
kEncodingX86M_NoSize, //!< X86 [M] (doesn't handle any size).
|
kEncodingX86M_NoSize, //!< X86 [M] (doesn't handle any size).
|
||||||
kEncodingX86M_GPB, //!< X86 [M] (handles single-byte size).
|
kEncodingX86M_GPB, //!< X86 [M] (handles single-byte size).
|
||||||
kEncodingX86M_GPB_MulDiv, //!< X86 [M] (like GPB, handles implicit|explicit MUL|DIV|IDIV).
|
kEncodingX86M_GPB_MulDiv, //!< X86 [M] (like GPB, handles implicit|explicit MUL|DIV|IDIV).
|
||||||
kEncodingX86M_Only, //!< X86 [M] (restricted to memory operand of any size).
|
kEncodingX86M_Only, //!< X86 [M] (restricted to memory operand of any size).
|
||||||
|
kEncodingX86M_Only_EDX_EAX, //!< X86 [M] (memory operand only, followed by implicit <edx> and <eax>).
|
||||||
kEncodingX86M_Nop, //!< X86 [M] (special case of NOP instruction).
|
kEncodingX86M_Nop, //!< X86 [M] (special case of NOP instruction).
|
||||||
kEncodingX86R_Native, //!< X86 [R] (register must be either 32-bit or 64-bit depending on arch).
|
kEncodingX86R_Native, //!< X86 [R] (register must be either 32-bit or 64-bit depending on arch).
|
||||||
kEncodingX86R_FromM, //!< X86 [R] - which specifies memory address.
|
kEncodingX86R_FromM, //!< X86 [R] - which specifies memory address.
|
||||||
@@ -121,7 +123,8 @@ enum EncodingId : uint32_t {
|
|||||||
kEncodingExtRm_XMM0, //!< EXT [RM<XMM0>].
|
kEncodingExtRm_XMM0, //!< EXT [RM<XMM0>].
|
||||||
kEncodingExtRm_ZDI, //!< EXT [RM<ZDI>].
|
kEncodingExtRm_ZDI, //!< EXT [RM<ZDI>].
|
||||||
kEncodingExtRm_P, //!< EXT [RM] (propagates 66H if the instruction uses XMM register).
|
kEncodingExtRm_P, //!< EXT [RM] (propagates 66H if the instruction uses XMM register).
|
||||||
kEncodingExtRm_Wx, //!< EXT [RM] (propagates REX.W if GPQ is used).
|
kEncodingExtRm_Wx, //!< EXT [RM] (propagates REX.W if GPQ is used or the second operand is GPQ/QWORD_PTR).
|
||||||
|
kEncodingExtRm_Wx_GpqOnly, //!< EXT [RM] (propagates REX.W if the first operand is GPQ register).
|
||||||
kEncodingExtRmRi, //!< EXT [RM|RI].
|
kEncodingExtRmRi, //!< EXT [RM|RI].
|
||||||
kEncodingExtRmRi_P, //!< EXT [RM|RI] (propagates 66H if the instruction uses XMM register).
|
kEncodingExtRmRi_P, //!< EXT [RM|RI] (propagates 66H if the instruction uses XMM register).
|
||||||
kEncodingExtRmi, //!< EXT [RMI].
|
kEncodingExtRmi, //!< EXT [RMI].
|
||||||
@@ -142,13 +145,15 @@ enum EncodingId : uint32_t {
|
|||||||
kEncodingVexM, //!< VEX|EVEX [M].
|
kEncodingVexM, //!< VEX|EVEX [M].
|
||||||
kEncodingVexM_VM, //!< VEX|EVEX [M] (propagates VEX|EVEX.L, VSIB support).
|
kEncodingVexM_VM, //!< VEX|EVEX [M] (propagates VEX|EVEX.L, VSIB support).
|
||||||
kEncodingVexMr_Lx, //!< VEX|EVEX [MR] (propagates VEX|EVEX.L if YMM used).
|
kEncodingVexMr_Lx, //!< VEX|EVEX [MR] (propagates VEX|EVEX.L if YMM used).
|
||||||
kEncodingVexMr_VM, //!< VEX|EVEX [MR] (propagates VEX|EVEX.L, VSIB support).
|
kEncodingVexMr_VM, //!< VEX|EVEX [MR] (VSIB support).
|
||||||
kEncodingVexMri, //!< VEX|EVEX [MRI].
|
kEncodingVexMri, //!< VEX|EVEX [MRI].
|
||||||
kEncodingVexMri_Lx, //!< VEX|EVEX [MRI] (propagates VEX|EVEX.L if YMM used).
|
kEncodingVexMri_Lx, //!< VEX|EVEX [MRI] (propagates VEX|EVEX.L if YMM used).
|
||||||
|
kEncodingVexMri_Vpextrw, //!< VEX|EVEX [MRI] (special case required by VPEXTRW instruction).
|
||||||
kEncodingVexRm, //!< VEX|EVEX [RM].
|
kEncodingVexRm, //!< VEX|EVEX [RM].
|
||||||
kEncodingVexRm_ZDI, //!< VEX|EVEX [RM<ZDI>].
|
kEncodingVexRm_ZDI, //!< VEX|EVEX [RM<ZDI>].
|
||||||
kEncodingVexRm_Wx, //!< VEX|EVEX [RM] (propagates VEX|EVEX.W if GPQ used).
|
kEncodingVexRm_Wx, //!< VEX|EVEX [RM] (propagates VEX|EVEX.W if GPQ used).
|
||||||
kEncodingVexRm_Lx, //!< VEX|EVEX [RM] (propagates VEX|EVEX.L if YMM used).
|
kEncodingVexRm_Lx, //!< VEX|EVEX [RM] (propagates VEX|EVEX.L if YMM used).
|
||||||
|
kEncodingVexRm_Lx_Narrow, //!< VEX|EVEX [RM] (the destination vector size is narrowed).
|
||||||
kEncodingVexRm_Lx_Bcst, //!< VEX|EVEX [RM] (can handle broadcast r32/r64).
|
kEncodingVexRm_Lx_Bcst, //!< VEX|EVEX [RM] (can handle broadcast r32/r64).
|
||||||
kEncodingVexRm_VM, //!< VEX|EVEX [RM] (propagates VEX|EVEX.L, VSIB support).
|
kEncodingVexRm_VM, //!< VEX|EVEX [RM] (propagates VEX|EVEX.L, VSIB support).
|
||||||
kEncodingVexRm_T1_4X, //!< EVEX [RM] (used by NN instructions that use RM-T1_4X encoding).
|
kEncodingVexRm_T1_4X, //!< EVEX [RM] (used by NN instructions that use RM-T1_4X encoding).
|
||||||
@@ -159,11 +164,14 @@ enum EncodingId : uint32_t {
|
|||||||
kEncodingVexRvm_Wx, //!< VEX|EVEX [RVM] (propagates VEX|EVEX.W if GPQ used).
|
kEncodingVexRvm_Wx, //!< VEX|EVEX [RVM] (propagates VEX|EVEX.W if GPQ used).
|
||||||
kEncodingVexRvm_ZDX_Wx, //!< VEX|EVEX [RVM<ZDX>] (propagates VEX|EVEX.W if GPQ used).
|
kEncodingVexRvm_ZDX_Wx, //!< VEX|EVEX [RVM<ZDX>] (propagates VEX|EVEX.W if GPQ used).
|
||||||
kEncodingVexRvm_Lx, //!< VEX|EVEX [RVM] (propagates VEX|EVEX.L if YMM used).
|
kEncodingVexRvm_Lx, //!< VEX|EVEX [RVM] (propagates VEX|EVEX.L if YMM used).
|
||||||
|
kEncodingVexRvm_Lx_KEvex, //!< VEX|EVEX [RVM] (forces EVEX prefix if K register is used on destination).
|
||||||
kEncodingVexRvm_Lx_2xK, //!< VEX|EVEX [RVM] (vp2intersectd/vp2intersectq).
|
kEncodingVexRvm_Lx_2xK, //!< VEX|EVEX [RVM] (vp2intersectd/vp2intersectq).
|
||||||
kEncodingVexRvmr, //!< VEX|EVEX [RVMR].
|
kEncodingVexRvmr, //!< VEX|EVEX [RVMR].
|
||||||
kEncodingVexRvmr_Lx, //!< VEX|EVEX [RVMR] (propagates VEX|EVEX.L if YMM used).
|
kEncodingVexRvmr_Lx, //!< VEX|EVEX [RVMR] (propagates VEX|EVEX.L if YMM used).
|
||||||
kEncodingVexRvmi, //!< VEX|EVEX [RVMI].
|
kEncodingVexRvmi, //!< VEX|EVEX [RVMI].
|
||||||
|
kEncodingVexRvmi_KEvex, //!< VEX|EVEX [RVMI] (forces EVEX prefix if K register is used on destination).
|
||||||
kEncodingVexRvmi_Lx, //!< VEX|EVEX [RVMI] (propagates VEX|EVEX.L if YMM used).
|
kEncodingVexRvmi_Lx, //!< VEX|EVEX [RVMI] (propagates VEX|EVEX.L if YMM used).
|
||||||
|
kEncodingVexRvmi_Lx_KEvex, //!< VEX|EVEX [RVMI] (forces EVEX prefix if K register is used on destination).
|
||||||
kEncodingVexRmv, //!< VEX|EVEX [RMV].
|
kEncodingVexRmv, //!< VEX|EVEX [RMV].
|
||||||
kEncodingVexRmv_Wx, //!< VEX|EVEX [RMV] (propagates VEX|EVEX.W if GPQ used).
|
kEncodingVexRmv_Wx, //!< VEX|EVEX [RMV] (propagates VEX|EVEX.W if GPQ used).
|
||||||
kEncodingVexRmv_VM, //!< VEX|EVEX [RMV] (propagates VEX|EVEX.L, VSIB support).
|
kEncodingVexRmv_VM, //!< VEX|EVEX [RMV] (propagates VEX|EVEX.L, VSIB support).
|
||||||
@@ -180,12 +188,13 @@ enum EncodingId : uint32_t {
|
|||||||
kEncodingVexRvmMvr_Lx, //!< VEX|EVEX [RVM|MVR] (propagates VEX|EVEX.L if YMM used).
|
kEncodingVexRvmMvr_Lx, //!< VEX|EVEX [RVM|MVR] (propagates VEX|EVEX.L if YMM used).
|
||||||
kEncodingVexRvmVmi, //!< VEX|EVEX [RVM|VMI].
|
kEncodingVexRvmVmi, //!< VEX|EVEX [RVM|VMI].
|
||||||
kEncodingVexRvmVmi_Lx, //!< VEX|EVEX [RVM|VMI] (propagates VEX|EVEX.L if YMM used).
|
kEncodingVexRvmVmi_Lx, //!< VEX|EVEX [RVM|VMI] (propagates VEX|EVEX.L if YMM used).
|
||||||
|
kEncodingVexRvmVmi_Lx_MEvex, //!< VEX|EVEX [RVM|VMI] (propagates EVEX if the second operand is memory).
|
||||||
kEncodingVexVm, //!< VEX|EVEX [VM].
|
kEncodingVexVm, //!< VEX|EVEX [VM].
|
||||||
kEncodingVexVm_Wx, //!< VEX|EVEX [VM] (propagates VEX|EVEX.W if GPQ used).
|
kEncodingVexVm_Wx, //!< VEX|EVEX [VM] (propagates VEX|EVEX.W if GPQ used).
|
||||||
kEncodingVexVmi, //!< VEX|EVEX [VMI].
|
kEncodingVexVmi, //!< VEX|EVEX [VMI].
|
||||||
kEncodingVexVmi_Lx, //!< VEX|EVEX [VMI] (propagates VEX|EVEX.L if YMM used).
|
kEncodingVexVmi_Lx, //!< VEX|EVEX [VMI] (propagates VEX|EVEX.L if YMM used).
|
||||||
kEncodingVexVmi4_Wx, //!< VEX|EVEX [VMI] (propagates VEX|EVEX.W if GPQ used, DWORD Immediate).
|
kEncodingVexVmi4_Wx, //!< VEX|EVEX [VMI] (propagates VEX|EVEX.W if GPQ used, DWORD Immediate).
|
||||||
kEncodingVexEvexVmi_Lx, //!< VEX|EVEX [VMI] (special, used by vpsrldq and vpslldq)
|
kEncodingVexVmi_Lx_MEvex, //!< VEX|EVEX [VMI] (force EVEX prefix when the second operand is memory)
|
||||||
kEncodingVexRvrmRvmr, //!< VEX|EVEX [RVRM|RVMR].
|
kEncodingVexRvrmRvmr, //!< VEX|EVEX [RVRM|RVMR].
|
||||||
kEncodingVexRvrmRvmr_Lx, //!< VEX|EVEX [RVRM|RVMR] (propagates VEX|EVEX.L if YMM used).
|
kEncodingVexRvrmRvmr_Lx, //!< VEX|EVEX [RVRM|RVMR] (propagates VEX|EVEX.L if YMM used).
|
||||||
kEncodingVexRvrmiRvmri_Lx, //!< VEX|EVEX [RVRMI|RVMRI] (propagates VEX|EVEX.L if YMM used).
|
kEncodingVexRvrmiRvmri_Lx, //!< VEX|EVEX [RVRMI|RVMRI] (propagates VEX|EVEX.L if YMM used).
|
||||||
@@ -244,6 +253,7 @@ struct RWInfo {
|
|||||||
kCategoryMovabs,
|
kCategoryMovabs,
|
||||||
kCategoryImul,
|
kCategoryImul,
|
||||||
kCategoryMovh64,
|
kCategoryMovh64,
|
||||||
|
kCategoryPunpcklxx,
|
||||||
kCategoryVmaskmov,
|
kCategoryVmaskmov,
|
||||||
kCategoryVmovddup,
|
kCategoryVmovddup,
|
||||||
kCategoryVmovmskpd,
|
kCategoryVmovmskpd,
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ struct Opcode {
|
|||||||
// instructions that use OPCODE+MOD/RM where both values in Mod/RM
|
// instructions that use OPCODE+MOD/RM where both values in Mod/RM
|
||||||
// are part of the opcode.
|
// are part of the opcode.
|
||||||
|
|
||||||
kModRM_Shift = 10,
|
kModRM_Shift = 13,
|
||||||
kModRM_Mask = 0x7u << kModRM_Shift,
|
kModRM_Mask = 0x7u << kModRM_Shift,
|
||||||
|
|
||||||
kModRM__ = 0x0u,
|
kModRM__ = 0x0u,
|
||||||
@@ -432,6 +432,10 @@ struct Opcode {
|
|||||||
return operator|=(mask[size & 0xF]);
|
return operator|=(mask[size & 0xF]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ASMJIT_INLINE Opcode& forceEvex() noexcept { return operator|=(kMM_ForceEvex); }
|
||||||
|
template<typename T>
|
||||||
|
ASMJIT_INLINE Opcode& forceEvexIf(T exp) noexcept { return operator|=(uint32_t(exp) << Support::constCtz(uint32_t(kMM_ForceEvex))); }
|
||||||
|
|
||||||
//! Extract `O` field (R) from the opcode (specified as /0..7 in instruction manuals).
|
//! Extract `O` field (R) from the opcode (specified as /0..7 in instruction manuals).
|
||||||
ASMJIT_INLINE uint32_t extractModO() const noexcept {
|
ASMJIT_INLINE uint32_t extractModO() const noexcept {
|
||||||
return (v >> kModO_Shift) & 0x07;
|
return (v >> kModO_Shift) & 0x07;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -3500,18 +3500,6 @@ static void generateOpcodes(asmjit::x86::Emitter* e, bool useRex1 = false, bool
|
|||||||
e->vandps(ymmA, ymmB, anyptr_gpC);
|
e->vandps(ymmA, ymmB, anyptr_gpC);
|
||||||
e->vandps(zmmA, zmmB, zmmC);
|
e->vandps(zmmA, zmmB, zmmC);
|
||||||
e->vandps(zmmA, zmmB, anyptr_gpC);
|
e->vandps(zmmA, zmmB, anyptr_gpC);
|
||||||
e->vblendmb(xmmA, xmmB, xmmC);
|
|
||||||
e->vblendmb(xmmA, xmmB, anyptr_gpC);
|
|
||||||
e->vblendmb(ymmA, ymmB, ymmC);
|
|
||||||
e->vblendmb(ymmA, ymmB, anyptr_gpC);
|
|
||||||
e->vblendmb(zmmA, zmmB, zmmC);
|
|
||||||
e->vblendmb(zmmA, zmmB, anyptr_gpC);
|
|
||||||
e->vblendmd(xmmA, xmmB, xmmC);
|
|
||||||
e->vblendmd(xmmA, xmmB, anyptr_gpC);
|
|
||||||
e->vblendmd(ymmA, ymmB, ymmC);
|
|
||||||
e->vblendmd(ymmA, ymmB, anyptr_gpC);
|
|
||||||
e->vblendmd(zmmA, zmmB, zmmC);
|
|
||||||
e->vblendmd(zmmA, zmmB, anyptr_gpC);
|
|
||||||
e->vblendmpd(xmmA, xmmB, xmmC);
|
e->vblendmpd(xmmA, xmmB, xmmC);
|
||||||
e->vblendmpd(xmmA, xmmB, anyptr_gpC);
|
e->vblendmpd(xmmA, xmmB, anyptr_gpC);
|
||||||
e->vblendmpd(ymmA, ymmB, ymmC);
|
e->vblendmpd(ymmA, ymmB, ymmC);
|
||||||
@@ -3524,18 +3512,6 @@ static void generateOpcodes(asmjit::x86::Emitter* e, bool useRex1 = false, bool
|
|||||||
e->vblendmps(ymmA, ymmB, anyptr_gpC);
|
e->vblendmps(ymmA, ymmB, anyptr_gpC);
|
||||||
e->vblendmps(zmmA, zmmB, zmmC);
|
e->vblendmps(zmmA, zmmB, zmmC);
|
||||||
e->vblendmps(zmmA, zmmB, anyptr_gpC);
|
e->vblendmps(zmmA, zmmB, anyptr_gpC);
|
||||||
e->vblendmq(xmmA, xmmB, xmmC);
|
|
||||||
e->vblendmq(xmmA, xmmB, anyptr_gpC);
|
|
||||||
e->vblendmq(ymmA, ymmB, ymmC);
|
|
||||||
e->vblendmq(ymmA, ymmB, anyptr_gpC);
|
|
||||||
e->vblendmq(zmmA, zmmB, zmmC);
|
|
||||||
e->vblendmq(zmmA, zmmB, anyptr_gpC);
|
|
||||||
e->vblendmw(xmmA, xmmB, xmmC);
|
|
||||||
e->vblendmw(xmmA, xmmB, anyptr_gpC);
|
|
||||||
e->vblendmw(ymmA, ymmB, ymmC);
|
|
||||||
e->vblendmw(ymmA, ymmB, anyptr_gpC);
|
|
||||||
e->vblendmw(zmmA, zmmB, zmmC);
|
|
||||||
e->vblendmw(zmmA, zmmB, anyptr_gpC);
|
|
||||||
e->vbroadcastf32x2(ymmA, xmmB);
|
e->vbroadcastf32x2(ymmA, xmmB);
|
||||||
e->vbroadcastf32x2(ymmA, anyptr_gpB);
|
e->vbroadcastf32x2(ymmA, anyptr_gpB);
|
||||||
e->vbroadcastf32x2(zmmA, xmmB);
|
e->vbroadcastf32x2(zmmA, xmmB);
|
||||||
@@ -4633,6 +4609,30 @@ static void generateOpcodes(asmjit::x86::Emitter* e, bool useRex1 = false, bool
|
|||||||
e->vpavgw(ymmA, ymmB, anyptr_gpC);
|
e->vpavgw(ymmA, ymmB, anyptr_gpC);
|
||||||
e->vpavgw(zmmA, zmmB, zmmC);
|
e->vpavgw(zmmA, zmmB, zmmC);
|
||||||
e->vpavgw(zmmA, zmmB, anyptr_gpC);
|
e->vpavgw(zmmA, zmmB, anyptr_gpC);
|
||||||
|
e->vpblendmb(xmmA, xmmB, xmmC);
|
||||||
|
e->vpblendmb(xmmA, xmmB, anyptr_gpC);
|
||||||
|
e->vpblendmb(ymmA, ymmB, ymmC);
|
||||||
|
e->vpblendmb(ymmA, ymmB, anyptr_gpC);
|
||||||
|
e->vpblendmb(zmmA, zmmB, zmmC);
|
||||||
|
e->vpblendmb(zmmA, zmmB, anyptr_gpC);
|
||||||
|
e->vpblendmd(xmmA, xmmB, xmmC);
|
||||||
|
e->vpblendmd(xmmA, xmmB, anyptr_gpC);
|
||||||
|
e->vpblendmd(ymmA, ymmB, ymmC);
|
||||||
|
e->vpblendmd(ymmA, ymmB, anyptr_gpC);
|
||||||
|
e->vpblendmd(zmmA, zmmB, zmmC);
|
||||||
|
e->vpblendmd(zmmA, zmmB, anyptr_gpC);
|
||||||
|
e->vpblendmq(xmmA, xmmB, xmmC);
|
||||||
|
e->vpblendmq(xmmA, xmmB, anyptr_gpC);
|
||||||
|
e->vpblendmq(ymmA, ymmB, ymmC);
|
||||||
|
e->vpblendmq(ymmA, ymmB, anyptr_gpC);
|
||||||
|
e->vpblendmq(zmmA, zmmB, zmmC);
|
||||||
|
e->vpblendmq(zmmA, zmmB, anyptr_gpC);
|
||||||
|
e->vpblendmw(xmmA, xmmB, xmmC);
|
||||||
|
e->vpblendmw(xmmA, xmmB, anyptr_gpC);
|
||||||
|
e->vpblendmw(ymmA, ymmB, ymmC);
|
||||||
|
e->vpblendmw(ymmA, ymmB, anyptr_gpC);
|
||||||
|
e->vpblendmw(zmmA, zmmB, zmmC);
|
||||||
|
e->vpblendmw(zmmA, zmmB, anyptr_gpC);
|
||||||
e->vpbroadcastb(xmmA, gdB);
|
e->vpbroadcastb(xmmA, gdB);
|
||||||
e->vpbroadcastb(xmmA, gzB);
|
e->vpbroadcastb(xmmA, gzB);
|
||||||
e->vpbroadcastb(xmmA, xmmB);
|
e->vpbroadcastb(xmmA, xmmB);
|
||||||
@@ -4657,12 +4657,12 @@ static void generateOpcodes(asmjit::x86::Emitter* e, bool useRex1 = false, bool
|
|||||||
e->vpbroadcastd(zmmA, gzB);
|
e->vpbroadcastd(zmmA, gzB);
|
||||||
e->vpbroadcastd(zmmA, xmmB);
|
e->vpbroadcastd(zmmA, xmmB);
|
||||||
e->vpbroadcastd(zmmA, anyptr_gpB);
|
e->vpbroadcastd(zmmA, anyptr_gpB);
|
||||||
e->vpbroadcastmb2d(xmmA, kB);
|
|
||||||
e->vpbroadcastmb2d(ymmA, kB);
|
|
||||||
e->vpbroadcastmb2d(zmmA, kB);
|
|
||||||
e->vpbroadcastmb2q(xmmA, kB);
|
e->vpbroadcastmb2q(xmmA, kB);
|
||||||
e->vpbroadcastmb2q(ymmA, kB);
|
e->vpbroadcastmb2q(ymmA, kB);
|
||||||
e->vpbroadcastmb2q(zmmA, kB);
|
e->vpbroadcastmb2q(zmmA, kB);
|
||||||
|
e->vpbroadcastmw2d(xmmA, kB);
|
||||||
|
e->vpbroadcastmw2d(ymmA, kB);
|
||||||
|
e->vpbroadcastmw2d(zmmA, kB);
|
||||||
if (isX64) e->vpbroadcastq(xmmA, gzB);
|
if (isX64) e->vpbroadcastq(xmmA, gzB);
|
||||||
e->vpbroadcastq(xmmA, xmmB);
|
e->vpbroadcastq(xmmA, xmmB);
|
||||||
e->vpbroadcastq(xmmA, anyptr_gpB);
|
e->vpbroadcastq(xmmA, anyptr_gpB);
|
||||||
|
|||||||
@@ -933,32 +933,18 @@ class OSignature {
|
|||||||
const index = asmdb.x86.Utils.regIndexOf(k);
|
const index = asmdb.x86.Utils.regIndexOf(k);
|
||||||
if (index !== null && index !== -1) {
|
if (index !== null && index !== -1) {
|
||||||
const kind = asmdb.x86.Utils.regKindOf(k);
|
const kind = asmdb.x86.Utils.regKindOf(k);
|
||||||
if (indexKind !== kind) return false;
|
if (indexKind !== kind)
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Can merge...
|
// Can merge...
|
||||||
for (k in bf) af[k] = true;
|
for (k in bf)
|
||||||
|
af[k] = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
simplify() {
|
|
||||||
const flags = this.flags;
|
|
||||||
|
|
||||||
// 32-bit register or 16-bit memory implies also 16-bit reg.
|
|
||||||
if (flags.r32 && flags.m16) {
|
|
||||||
flags.r16 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 32-bit register or 8-bit memory implies also 16-bit and 8-bit reg.
|
|
||||||
if (flags.r32 && flags.m8) {
|
|
||||||
flags.r8lo = true;
|
|
||||||
flags.r8hi = true;
|
|
||||||
flags.r16 = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
var s = "";
|
var s = "";
|
||||||
var flags = this.flags;
|
var flags = this.flags;
|
||||||
@@ -1124,11 +1110,6 @@ class ISignature extends Array {
|
|||||||
this.implicit = 0; // Number of implicit operands.
|
this.implicit = 0; // Number of implicit operands.
|
||||||
}
|
}
|
||||||
|
|
||||||
simplify() {
|
|
||||||
for (var i = 0; i < this.length; i++)
|
|
||||||
this[i].simplify();
|
|
||||||
}
|
|
||||||
|
|
||||||
opEquals(other) {
|
opEquals(other) {
|
||||||
const len = this.length;
|
const len = this.length;
|
||||||
if (len !== other.length) return false;
|
if (len !== other.length) return false;
|
||||||
@@ -1321,21 +1302,21 @@ class SignatureArray extends Array {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
simplify() {
|
|
||||||
for (var i = 0; i < this.length; i++)
|
|
||||||
this[i].simplify();
|
|
||||||
}
|
|
||||||
|
|
||||||
compact() {
|
compact() {
|
||||||
for (var i = 0; i < this.length; i++) {
|
var didSomething = true;
|
||||||
var row = this[i];
|
while (didSomething) {
|
||||||
var j = i + 1;
|
didSomething = false;
|
||||||
while (j < this.length) {
|
for (var i = 0; i < this.length; i++) {
|
||||||
if (row.mergeWith(this[j])) {
|
var row = this[i];
|
||||||
this.splice(j, 1);
|
var j = i + 1;
|
||||||
continue;
|
while (j < this.length) {
|
||||||
|
if (row.mergeWith(this[j])) {
|
||||||
|
this.splice(j, 1);
|
||||||
|
didSomething = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
j++;
|
||||||
}
|
}
|
||||||
j++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1530,7 +1511,6 @@ class InstSignatureTable extends core.Task {
|
|||||||
if (inst.name === "mov" && mem.startsWith("moff"))
|
if (inst.name === "mov" && mem.startsWith("moff"))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (reg === "r8") reg = "r8lo";
|
|
||||||
if (reg === "seg") reg = "sreg";
|
if (reg === "seg") reg = "sreg";
|
||||||
if (reg === "st(i)") reg = "st";
|
if (reg === "st(i)") reg = "st";
|
||||||
if (reg === "st(0)") reg = "st0";
|
if (reg === "st(0)") reg = "st0";
|
||||||
@@ -1571,6 +1551,46 @@ class InstSignatureTable extends core.Task {
|
|||||||
|
|
||||||
const seg = iop.memSeg;
|
const seg = iop.memSeg;
|
||||||
if (seg) {
|
if (seg) {
|
||||||
|
switch (inst.name) {
|
||||||
|
case "cmpsb": op.flags.m8 = true; break;
|
||||||
|
case "cmpsw": op.flags.m16 = true; break;
|
||||||
|
case "cmpsd": op.flags.m32 = true; break;
|
||||||
|
case "cmpsq": op.flags.m64 = true; break;
|
||||||
|
case "lodsb": op.flags.m8 = true; break;
|
||||||
|
case "lodsw": op.flags.m16 = true; break;
|
||||||
|
case "lodsd": op.flags.m32 = true; break;
|
||||||
|
case "lodsq": op.flags.m64 = true; break;
|
||||||
|
case "movsb": op.flags.m8 = true; break;
|
||||||
|
case "movsw": op.flags.m16 = true; break;
|
||||||
|
case "movsd": op.flags.m32 = true; break;
|
||||||
|
case "movsq": op.flags.m64 = true; break;
|
||||||
|
case "scasb": op.flags.m8 = true; break;
|
||||||
|
case "scasw": op.flags.m16 = true; break;
|
||||||
|
case "scasd": op.flags.m32 = true; break;
|
||||||
|
case "scasq": op.flags.m64 = true; break;
|
||||||
|
case "stosb": op.flags.m8 = true; break;
|
||||||
|
case "stosw": op.flags.m16 = true; break;
|
||||||
|
case "stosd": op.flags.m32 = true; break;
|
||||||
|
case "stosq": op.flags.m64 = true; break;
|
||||||
|
case "insb": op.flags.m8 = true; break;
|
||||||
|
case "insw": op.flags.m16 = true; break;
|
||||||
|
case "insd": op.flags.m32 = true; break;
|
||||||
|
case "outsb": op.flags.m8 = true; break;
|
||||||
|
case "outsw": op.flags.m16 = true; break;
|
||||||
|
case "outsd": op.flags.m32 = true; break;
|
||||||
|
case "clzero": op.flags.mem = true; op.flags.m512 = true; break;
|
||||||
|
case "enqcmd": op.flags.mem = true; op.flags.m512 = true; break;
|
||||||
|
case "enqcmds": op.flags.mem = true; op.flags.m512 = true; break;
|
||||||
|
case "movdir64b": op.flags.mem = true; op.flags.m512 = true; break;
|
||||||
|
case "maskmovq": op.flags.mem = true; op.flags.m64 = true; break;
|
||||||
|
case "maskmovdqu": op.flags.mem = true; op.flags.m128 = true; break;
|
||||||
|
case "vmaskmovdqu": op.flags.mem = true; op.flags.m128 = true; break;
|
||||||
|
case "monitor": op.flags.mem = true; break;
|
||||||
|
case "monitorx": op.flags.mem = true; break;
|
||||||
|
case "umonitor": op.flags.mem = true; break;
|
||||||
|
default: console.log(`UNKNOWN MEM IN INSTRUCTION '${inst.name}'`); break;
|
||||||
|
}
|
||||||
|
|
||||||
if (seg === "ds") op.flags.memDS = true;
|
if (seg === "ds") op.flags.memDS = true;
|
||||||
if (seg === "es") op.flags.memES = true;
|
if (seg === "es") op.flags.memES = true;
|
||||||
if (reg === "reg") { op.flags.memBase = true; }
|
if (reg === "reg") { op.flags.memBase = true; }
|
||||||
@@ -1581,13 +1601,26 @@ class InstSignatureTable extends core.Task {
|
|||||||
if (reg === "zdi") { op.flags.memBase = true; op.flags.memZDI = true; }
|
if (reg === "zdi") { op.flags.memBase = true; op.flags.memZDI = true; }
|
||||||
}
|
}
|
||||||
else if (reg) {
|
else if (reg) {
|
||||||
op.flags[reg] = true;
|
if (reg == "r8") {
|
||||||
if (reg === "r8lo") op.flags.r8hi = true;
|
op.flags["r8lo"] = true;
|
||||||
|
op.flags["r8hi"] = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
op.flags[reg] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (mem) {
|
if (mem) {
|
||||||
op.flags[mem] = true;
|
op.flags[mem] = true;
|
||||||
// Exception: Allow LEA to use any memory size.
|
// HACK: Allow LEA to use any memory size.
|
||||||
if (inst.name === "lea") MapUtils.add(op.flags, MemOp);
|
if (inst.name === "lea") {
|
||||||
|
op.flags.mem = true;
|
||||||
|
Object.assign(op.flags, MemOp);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HACK: These instructions specify explicit memory size, but it's just informational.
|
||||||
|
if (inst.name === "enqcmd" || inst.name === "enqcmds" || inst.name === "movdir64b")
|
||||||
|
op.flags.mem = true;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (imm) {
|
if (imm) {
|
||||||
if (iop.immSign === "any" || iop.immSign === "signed" ) op.flags["i" + imm] = true;
|
if (iop.immSign === "any" || iop.immSign === "signed" ) op.flags["i" + imm] = true;
|
||||||
@@ -1607,12 +1640,7 @@ class InstSignatureTable extends core.Task {
|
|||||||
if (signatures.length && GenUtils.canUseImplicitMemSize(dbInsts[0].name))
|
if (signatures.length && GenUtils.canUseImplicitMemSize(dbInsts[0].name))
|
||||||
signatures.calcImplicitMemSize();
|
signatures.calcImplicitMemSize();
|
||||||
|
|
||||||
signatures.simplify();
|
|
||||||
signatures.compact();
|
signatures.compact();
|
||||||
|
|
||||||
signatures.simplify();
|
|
||||||
signatures.compact();
|
|
||||||
|
|
||||||
return signatures;
|
return signatures;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1745,6 +1773,9 @@ class InstRWInfoTable extends core.Task {
|
|||||||
"movabs" : "Movabs",
|
"movabs" : "Movabs",
|
||||||
"movhpd" : "Movh64",
|
"movhpd" : "Movh64",
|
||||||
"movhps" : "Movh64",
|
"movhps" : "Movh64",
|
||||||
|
"punpcklbw" : "Punpcklxx",
|
||||||
|
"punpckldq" : "Punpcklxx",
|
||||||
|
"punpcklwd" : "Punpcklxx",
|
||||||
"vmaskmovpd": "Vmaskmov",
|
"vmaskmovpd": "Vmaskmov",
|
||||||
"vmaskmovps": "Vmaskmov",
|
"vmaskmovps": "Vmaskmov",
|
||||||
"vmovddup" : "Vmovddup",
|
"vmovddup" : "Vmovddup",
|
||||||
@@ -2153,9 +2184,14 @@ class InstRWInfoTable extends core.Task {
|
|||||||
if (category === null)
|
if (category === null)
|
||||||
category = c;
|
category = c;
|
||||||
else if (category !== c) {
|
else if (category !== c) {
|
||||||
|
// Special cases.
|
||||||
if (dbInst.name === "mov" || dbInst.name === "vmovddup")
|
if (dbInst.name === "mov" || dbInst.name === "vmovddup")
|
||||||
return "None"; // Special case
|
return "None";
|
||||||
return StringUtils.capitalize(dbInst.name); // Special case.
|
|
||||||
|
if (/^(punpcklbw|punpckldq|punpcklwd)$/.test(dbInst.name))
|
||||||
|
return "None";
|
||||||
|
|
||||||
|
return StringUtils.capitalize(dbInst.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user