mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-16 20:17:05 +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: "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-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" }
|
||||
- { 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" }
|
||||
|
||||
# Disabled, because of GitHub actions infrastructure issues (builds not starting).
|
||||
#- { 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" }
|
||||
#- { 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: "Release", defs: "ASMJIT_TEST=ON" }
|
||||
|
||||
@@ -437,14 +437,14 @@ public:
|
||||
if (immSize >= 4) {
|
||||
emit32uLE(imm & 0xFFFFFFFFu);
|
||||
imm >>= 32;
|
||||
immSize -= 4;
|
||||
immSize = FastUInt8(immSize - 4u);
|
||||
}
|
||||
#else
|
||||
uint32_t imm = uint32_t(immValue & 0xFFFFFFFFu);
|
||||
if (immSize >= 4) {
|
||||
emit32uLE(imm);
|
||||
imm = uint32_t(immValue >> 32);
|
||||
immSize -= 4;
|
||||
immSize = FastUInt8(immSize - 4u);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -697,7 +697,8 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(uint32_t instId, const Operand_& o0, c
|
||||
goto EmitX86R;
|
||||
|
||||
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;
|
||||
|
||||
rbReg = opcode.extractModRM();
|
||||
@@ -755,11 +756,17 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(uint32_t instId, const Operand_& o0, c
|
||||
}
|
||||
break;
|
||||
|
||||
case InstDB::kEncodingX86M_NoMemSize:
|
||||
if (o0.isReg())
|
||||
opcode.addPrefixBySize(o0.size());
|
||||
goto CaseX86M_NoSize;
|
||||
|
||||
case InstDB::kEncodingX86M:
|
||||
opcode.addPrefixBySize(o0.size());
|
||||
ASMJIT_FALLTHROUGH;
|
||||
|
||||
case InstDB::kEncodingX86M_NoSize:
|
||||
CaseX86M_NoSize:
|
||||
rbReg = o0.id();
|
||||
if (isign3 == ENC_OPS1(Reg))
|
||||
goto EmitX86R;
|
||||
@@ -839,6 +846,13 @@ CaseX86M_GPB_MulDiv:
|
||||
}
|
||||
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:
|
||||
if (isign3 == ENC_OPS1(Mem)) {
|
||||
rmRel = &o0;
|
||||
@@ -977,34 +991,27 @@ CaseX86M_GPB_MulDiv:
|
||||
|
||||
case InstDB::kEncodingX86Arith:
|
||||
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
||||
opcode += 2;
|
||||
opcode.addArithBySize(o0.size());
|
||||
|
||||
if (o0.size() != o1.size())
|
||||
goto OperandSizeMismatch;
|
||||
|
||||
opReg = o0.id();
|
||||
rbReg = o1.id();
|
||||
rbReg = o0.id();
|
||||
opReg = o1.id();
|
||||
|
||||
if (o0.size() == 1) {
|
||||
FIXUP_GPB(o0, opReg);
|
||||
FIXUP_GPB(o1, rbReg);
|
||||
|
||||
if (!(options & Inst::kOptionModMR))
|
||||
goto EmitX86R;
|
||||
|
||||
opcode -= 2;
|
||||
std::swap(opReg, rbReg);
|
||||
goto EmitX86R;
|
||||
FIXUP_GPB(o0, rbReg);
|
||||
FIXUP_GPB(o1, opReg);
|
||||
}
|
||||
else {
|
||||
if (!(options & Inst::kOptionModMR))
|
||||
goto EmitX86R;
|
||||
|
||||
opcode -= 2;
|
||||
std::swap(opReg, rbReg);
|
||||
// MOD/MR: The default encoding used if not instructed otherwise..
|
||||
if (!(options & Inst::kOptionModRM))
|
||||
goto EmitX86R;
|
||||
}
|
||||
|
||||
// MOD/RM: Alternative encoding selected via instruction options.
|
||||
opcode += 2;
|
||||
std::swap(opReg, rbReg);
|
||||
goto EmitX86R;
|
||||
}
|
||||
|
||||
if (isign3 == ENC_OPS2(Reg, Mem)) {
|
||||
@@ -1211,7 +1218,7 @@ CaseX86M_GPB_MulDiv:
|
||||
if (o1.size() != 1)
|
||||
goto EmitX86M;
|
||||
|
||||
FIXUP_GPB(o0, opReg);
|
||||
FIXUP_GPB(o1, opReg);
|
||||
goto EmitX86M;
|
||||
}
|
||||
break;
|
||||
@@ -1436,6 +1443,8 @@ CaseX86M_GPB_MulDiv:
|
||||
}
|
||||
|
||||
if (isign3 == ENC_OPS1(Mem)) {
|
||||
if (!o0.size())
|
||||
goto AmbiguousOperandSize;
|
||||
opcode.addArithBySize(o0.size());
|
||||
rmRel = &o0;
|
||||
goto EmitX86M;
|
||||
@@ -1539,9 +1548,6 @@ CaseX86M_GPB_MulDiv:
|
||||
case InstDB::kEncodingX86Mov:
|
||||
// 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
|
||||
// "no segment register used". We have to fix this (decrement the index
|
||||
// of the register) when emitting MOV instructions which move to/from
|
||||
@@ -1550,47 +1556,46 @@ CaseX86M_GPB_MulDiv:
|
||||
|
||||
// GP <- ??
|
||||
if (Reg::isGp(o0)) {
|
||||
rbReg = o0.id();
|
||||
opReg = o1.id();
|
||||
|
||||
// GP <- GP
|
||||
if (Reg::isGp(o1)) {
|
||||
uint32_t size0 = o0.size();
|
||||
uint32_t size1 = o1.size();
|
||||
|
||||
if (size0 != size1) {
|
||||
uint32_t opSize = o0.size();
|
||||
if (opSize != o1.size()) {
|
||||
// TODO: [X86 Assembler] This is a non-standard extension, which should be removed.
|
||||
// We allow 'mov r64, r32' as it's basically zero-extend.
|
||||
if (size0 == 8 && size1 == 4)
|
||||
size0 = 4; // Zero extend, don't promote to 64-bit.
|
||||
if (opSize == 8 && o1.size() == 4)
|
||||
opSize = 4; // Zero extend, don't promote to 64-bit.
|
||||
else
|
||||
goto InvalidInstruction;
|
||||
}
|
||||
|
||||
if (size0 == 1) {
|
||||
FIXUP_GPB(o0, opReg);
|
||||
FIXUP_GPB(o1, rbReg);
|
||||
opcode = 0x8A;
|
||||
if (opSize == 1) {
|
||||
FIXUP_GPB(o0, rbReg);
|
||||
FIXUP_GPB(o1, opReg);
|
||||
opcode = 0x88;
|
||||
|
||||
if (!(options & Inst::kOptionModMR))
|
||||
if (!(options & Inst::kOptionModRM))
|
||||
goto EmitX86R;
|
||||
|
||||
opcode -= 2;
|
||||
opcode += 2;
|
||||
std::swap(opReg, rbReg);
|
||||
goto EmitX86R;
|
||||
}
|
||||
else {
|
||||
opcode = 0x8B;
|
||||
opcode.addPrefixBySize(size0);
|
||||
opcode = 0x89;
|
||||
opcode.addPrefixBySize(opSize);
|
||||
|
||||
if (!(options & Inst::kOptionModMR))
|
||||
if (!(options & Inst::kOptionModRM))
|
||||
goto EmitX86R;
|
||||
|
||||
opcode -= 2;
|
||||
opcode += 2;
|
||||
std::swap(opReg, rbReg);
|
||||
goto EmitX86R;
|
||||
}
|
||||
}
|
||||
|
||||
opReg = rbReg;
|
||||
rbReg = o0.id();
|
||||
|
||||
// GP <- SReg
|
||||
if (Reg::isSReg(o1)) {
|
||||
opcode = 0x8C;
|
||||
@@ -1618,6 +1623,9 @@ CaseX86M_GPB_MulDiv:
|
||||
}
|
||||
}
|
||||
else {
|
||||
opReg = o0.id();
|
||||
rbReg = o1.id();
|
||||
|
||||
// ?? <- GP
|
||||
if (!Reg::isGp(o1))
|
||||
goto InvalidInstruction;
|
||||
@@ -1952,7 +1960,7 @@ CaseX86M_GPB_MulDiv:
|
||||
goto InvalidSegment;
|
||||
|
||||
opcode = x86OpcodePopSReg[segment];
|
||||
goto EmitDone;
|
||||
goto EmitX86Op;
|
||||
}
|
||||
else {
|
||||
CaseX86PushPop_Gp:
|
||||
@@ -2032,6 +2040,8 @@ CaseX86PushPop_Gp:
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ASMJIT_UNLIKELY(o0.size() == 0))
|
||||
goto AmbiguousOperandSize;
|
||||
opcode.addArithBySize(o0.size());
|
||||
|
||||
if (isign3 == ENC_OPS2(Mem, Reg)) {
|
||||
@@ -2044,9 +2054,6 @@ CaseX86PushPop_Gp:
|
||||
}
|
||||
|
||||
if (isign3 == ENC_OPS2(Mem, Imm)) {
|
||||
if (ASMJIT_UNLIKELY(o0.size() == 0))
|
||||
goto AmbiguousOperandSize;
|
||||
|
||||
rmRel = &o0;
|
||||
immValue = o1.as<Imm>().value() & 0xFF;
|
||||
immSize = 0;
|
||||
@@ -2257,30 +2264,45 @@ CaseX86PushPop_Gp:
|
||||
|
||||
case InstDB::kEncodingX86Xadd:
|
||||
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
||||
opcode.addArithBySize(o0.size());
|
||||
rbReg = o0.id();
|
||||
opReg = o1.id();
|
||||
|
||||
if (o0.size() != o1.size())
|
||||
uint32_t opSize = o0.size();
|
||||
if (opSize != o1.size())
|
||||
goto OperandSizeMismatch;
|
||||
|
||||
if (o0.size() == 1) {
|
||||
if (opSize == 1) {
|
||||
FIXUP_GPB(o0, rbReg);
|
||||
FIXUP_GPB(o1, opReg);
|
||||
goto EmitX86R;
|
||||
}
|
||||
|
||||
// Special opcode for 'xchg ?ax, reg'.
|
||||
// Special cases for 'xchg ?ax, reg'.
|
||||
if (instId == Inst::kIdXchg && (opReg == 0 || rbReg == 0)) {
|
||||
opcode &= Opcode::kPP_66 | Opcode::kW;
|
||||
opcode |= 0x90;
|
||||
// One of `xchg a, b` or `xchg b, a` is AX/EAX/RAX.
|
||||
opReg += rbReg;
|
||||
goto EmitX86OpReg;
|
||||
}
|
||||
else {
|
||||
goto EmitX86R;
|
||||
if (is64Bit() && opReg == rbReg && opSize >= 4) {
|
||||
if (opSize == 8) {
|
||||
// Encode 'xchg rax, rax' as '90' (REX and other prefixes are optional).
|
||||
opcode &= Opcode::kW;
|
||||
opcode |= 0x90;
|
||||
goto EmitX86OpReg;
|
||||
}
|
||||
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)) {
|
||||
@@ -2700,7 +2722,11 @@ CaseExtMovd:
|
||||
goto CaseExtRm;
|
||||
|
||||
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;
|
||||
|
||||
case InstDB::kEncodingExtRm:
|
||||
@@ -2843,15 +2869,15 @@ CaseExtRm:
|
||||
if (isign3 == ENC_OPS2(Reg, Reg))
|
||||
goto EmitX86R;
|
||||
|
||||
// The following instruction uses the secondary opcode.
|
||||
opcode = x86AltOpcodeOf(instInfo);
|
||||
|
||||
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>()) ) +
|
||||
(uint32_t(o2.as<Imm>().valueAs<uint8_t>()) << 8) ;
|
||||
immSize = 2;
|
||||
|
||||
rbReg = opcode.extractModO();
|
||||
goto EmitX86R;
|
||||
}
|
||||
break;
|
||||
@@ -2866,10 +2892,10 @@ CaseExtRm:
|
||||
if (isign4 == ENC_OPS2(Reg, Reg))
|
||||
goto EmitX86R;
|
||||
|
||||
// The following instruction uses the secondary opcode.
|
||||
opcode = x86AltOpcodeOf(instInfo);
|
||||
|
||||
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>()) ) +
|
||||
(uint32_t(o3.as<Imm>().valueAs<uint8_t>()) << 8) ;
|
||||
immSize = 2;
|
||||
@@ -2971,7 +2997,6 @@ CaseExtRm:
|
||||
|
||||
case InstDB::kEncodingVexM_VM:
|
||||
if (isign3 == ENC_OPS1(Mem)) {
|
||||
opcode |= x86OpcodeLByVMem(o0);
|
||||
rmRel = &o0;
|
||||
goto EmitVexEvexM;
|
||||
}
|
||||
@@ -3003,11 +3028,27 @@ CaseExtRm:
|
||||
}
|
||||
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:
|
||||
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
||||
ASMJIT_FALLTHROUGH;
|
||||
|
||||
case InstDB::kEncodingVexMri:
|
||||
CaseVexMri:
|
||||
immValue = o2.as<Imm>().value();
|
||||
immSize = 1;
|
||||
|
||||
@@ -3035,6 +3076,13 @@ CaseExtRm:
|
||||
opcode.addWIf(Reg::isGpq(o0) | Reg::isGpq(o1));
|
||||
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:
|
||||
if (isign3 == ENC_OPS2(Reg, Reg) && Reg::isGp(o1.as<Reg>())) {
|
||||
opcode = x86AltOpcodeOf(instInfo) | x86OpcodeLBySize(o0.size() | o1.size());
|
||||
@@ -3077,7 +3125,7 @@ CaseVexRm:
|
||||
const Operand_& o4 = opExt[EmitterUtils::kOp4];
|
||||
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.
|
||||
uint32_t i1 = o1.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))
|
||||
goto NotConsecutiveRegs;
|
||||
|
||||
opReg = o0.id();
|
||||
opReg = x86PackRegAndVvvvv(o0.id(), i1);
|
||||
rmRel = &o5;
|
||||
goto EmitVexEvexM;
|
||||
}
|
||||
@@ -3148,6 +3196,11 @@ CaseVexRvm_R:
|
||||
goto CaseVexRvm;
|
||||
}
|
||||
|
||||
case InstDB::kEncodingVexRvm_Lx_KEvex: {
|
||||
opcode.forceEvexIf(Reg::isKReg(o0));
|
||||
ASMJIT_FALLTHROUGH;
|
||||
}
|
||||
|
||||
case InstDB::kEncodingVexRvm_Lx: {
|
||||
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
||||
goto CaseVexRvm;
|
||||
@@ -3205,11 +3258,21 @@ CaseVexRvm_R:
|
||||
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:
|
||||
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
||||
ASMJIT_FALLTHROUGH;
|
||||
|
||||
case InstDB::kEncodingVexRvmi: {
|
||||
case InstDB::kEncodingVexRvmi:
|
||||
VexRvmi:
|
||||
{
|
||||
const Operand_& o3 = opExt[EmitterUtils::kOp3];
|
||||
const uint32_t isign4 = isign3 + (o3.opType() << 9);
|
||||
|
||||
@@ -3257,7 +3320,6 @@ CaseVexRvm_R:
|
||||
rmRel = &o1;
|
||||
goto EmitVexEvexM;
|
||||
}
|
||||
|
||||
ASMJIT_FALLTHROUGH;
|
||||
|
||||
case InstDB::kEncodingVexRmv_VM:
|
||||
@@ -3542,6 +3604,10 @@ CaseVexRvm_R:
|
||||
}
|
||||
break;
|
||||
|
||||
case InstDB::kEncodingVexRvmVmi_Lx_MEvex:
|
||||
opcode.forceEvexIf(o1.isMem());
|
||||
ASMJIT_FALLTHROUGH;
|
||||
|
||||
case InstDB::kEncodingVexRvmVmi_Lx:
|
||||
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
||||
ASMJIT_FALLTHROUGH;
|
||||
@@ -3560,7 +3626,7 @@ CaseVexRvm_R:
|
||||
}
|
||||
|
||||
// The following instruction uses the secondary opcode.
|
||||
opcode &= Opcode::kLL_Mask;
|
||||
opcode &= Opcode::kLL_Mask | Opcode::kMM_ForceEvex;
|
||||
opcode |= x86AltOpcodeOf(instInfo);
|
||||
opReg = opcode.extractModO();
|
||||
|
||||
@@ -3598,9 +3664,9 @@ CaseVexRvm_R:
|
||||
}
|
||||
break;
|
||||
|
||||
case InstDB::kEncodingVexEvexVmi_Lx:
|
||||
case InstDB::kEncodingVexVmi_Lx_MEvex:
|
||||
if (isign3 == ENC_OPS3(Reg, Mem, Imm))
|
||||
opcode |= Opcode::kMM_ForceEvex;
|
||||
opcode.forceEvex();
|
||||
ASMJIT_FALLTHROUGH;
|
||||
|
||||
case InstDB::kEncodingVexVmi_Lx:
|
||||
@@ -3743,11 +3809,24 @@ CaseVexVmi_AfterImm:
|
||||
|
||||
if (isign4 == ENC_OPS4(Reg, Reg, Reg, Reg)) {
|
||||
opReg = x86PackRegAndVvvvv(o0.id(), o1.id());
|
||||
rbReg = o2.id();
|
||||
|
||||
immValue = o3.id() << 4;
|
||||
immSize = 1;
|
||||
goto EmitVexEvexR;
|
||||
if (!(options & Inst::kOptionModMR)) {
|
||||
// MOD/RM - Encoding preferred by LLVM.
|
||||
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)) {
|
||||
|
||||
@@ -340,9 +340,10 @@ public:
|
||||
//! \name Encoding Options
|
||||
//! \{
|
||||
|
||||
//! Prefer MOD_MR encoding over MOD_RM (the default) when encoding instruction
|
||||
//! that allows both. This option is only applicable to instructions where both
|
||||
//! operands are registers.
|
||||
//! Prefer MOD/RM encoding when both MOD/RM and MOD/MR forms are applicable.
|
||||
inline This& mod_rm() noexcept { return _addInstOptions(Inst::kOptionModRM); }
|
||||
|
||||
//! Prefer MOD/MR encoding when both MOD/RM and MOD/MR forms are applicable.
|
||||
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, Mem, Gp) // ANY
|
||||
ASMJIT_INST_2x(test, Test, Mem, Imm) // ANY
|
||||
ASMJIT_INST_1x(ud0, Ud0, Reg) // ANY
|
||||
ASMJIT_INST_1x(ud0, Ud0, Mem) // ANY
|
||||
ASMJIT_INST_1x(ud1, Ud1, Reg) // ANY
|
||||
ASMJIT_INST_1x(ud1, Ud1, Mem) // ANY
|
||||
ASMJIT_INST_2x(ud0, Ud0, Gp, Gp) // ANY
|
||||
ASMJIT_INST_2x(ud0, Ud0, Gp, Mem) // ANY
|
||||
ASMJIT_INST_2x(ud1, Ud1, Gp, Gp) // ANY
|
||||
ASMJIT_INST_2x(ud1, Ud1, Gp, Mem) // ANY
|
||||
ASMJIT_INST_0x(ud2, Ud2) // ANY
|
||||
ASMJIT_INST_2x(xadd, Xadd, Gp, Gp) // ANY
|
||||
ASMJIT_INST_2x(xadd, Xadd, Mem, Gp) // ANY
|
||||
@@ -993,7 +994,19 @@ public:
|
||||
//! \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
|
||||
//! \{
|
||||
|
||||
ASMJIT_INST_3x(monitorx, Monitorx, Mem, Gp, Gp)
|
||||
ASMJIT_INST_3x(mwaitx, Mwaitx, Gp, Gp, Gp)
|
||||
ASMJIT_INST_3x(monitorx, Monitorx, Mem, Gp, Gp) // MONITORX
|
||||
ASMJIT_INST_3x(mwaitx, Mwaitx, Gp, Gp, Gp) // MONITORX
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -1049,9 +1062,9 @@ public:
|
||||
//! \name WAITPKG Instructions
|
||||
//! \{
|
||||
|
||||
ASMJIT_INST_3x(tpause, Tpause, Gp, Gp, Gp)
|
||||
ASMJIT_INST_1x(umonitor, Umonitor, Mem)
|
||||
ASMJIT_INST_3x(umwait, Umwait, Gp, Gp, Gp)
|
||||
ASMJIT_INST_3x(tpause, Tpause, Gp, Gp, Gp) // WAITPKG
|
||||
ASMJIT_INST_1x(umonitor, Umonitor, Mem) // WAITPKG
|
||||
ASMJIT_INST_3x(umwait, Umwait, Gp, Gp, Gp) // WAITPKG
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -1089,36 +1102,58 @@ public:
|
||||
//! \name TSXLDTRK Instructions
|
||||
//! \{
|
||||
|
||||
ASMJIT_INST_0x(xresldtrk, Xresldtrk)
|
||||
ASMJIT_INST_0x(xsusldtrk, Xsusldtrk)
|
||||
ASMJIT_INST_0x(xresldtrk, Xresldtrk) // TSXLDTRK
|
||||
ASMJIT_INST_0x(xsusldtrk, Xsusldtrk) // TSXLDTRK
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name CET-IBT Instructions
|
||||
//! \{
|
||||
|
||||
ASMJIT_INST_0x(endbr32, Endbr32)
|
||||
ASMJIT_INST_0x(endbr64, Endbr64)
|
||||
ASMJIT_INST_0x(endbr32, Endbr32) // CET_IBT
|
||||
ASMJIT_INST_0x(endbr64, Endbr64) // CET_IBT
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name CET-SS Instructions
|
||||
//! \{
|
||||
|
||||
ASMJIT_INST_1x(clrssbsy, Clrssbsy, Mem)
|
||||
ASMJIT_INST_0x(setssbsy, Setssbsy)
|
||||
ASMJIT_INST_1x(clrssbsy, Clrssbsy, Mem) // CET_SS
|
||||
ASMJIT_INST_0x(setssbsy, Setssbsy) // CET_SS
|
||||
|
||||
ASMJIT_INST_1x(rstorssp, Rstorssp, Mem)
|
||||
ASMJIT_INST_0x(saveprevssp, Saveprevssp)
|
||||
ASMJIT_INST_1x(rstorssp, Rstorssp, Mem) // CET_SS
|
||||
ASMJIT_INST_0x(saveprevssp, Saveprevssp) // CET_SS
|
||||
|
||||
ASMJIT_INST_1x(incsspd, Incsspd, Gp)
|
||||
ASMJIT_INST_1x(incsspq, Incsspq, Gp)
|
||||
ASMJIT_INST_1x(rdsspd, Rdsspd, Gp)
|
||||
ASMJIT_INST_1x(rdsspq, Rdsspq, Gp)
|
||||
ASMJIT_INST_2x(wrssd, Wrssd, Mem, Gp)
|
||||
ASMJIT_INST_2x(wrssq, Wrssq, Mem, Gp)
|
||||
ASMJIT_INST_2x(wrussd, Wrussd, Mem, Gp)
|
||||
ASMJIT_INST_2x(wrussq, Wrussq, Mem, Gp)
|
||||
ASMJIT_INST_1x(incsspd, Incsspd, Gp) // CET_SS
|
||||
ASMJIT_INST_1x(incsspq, Incsspq, Gp) // CET_SS
|
||||
ASMJIT_INST_1x(rdsspd, Rdsspd, Gp) // CET_SS
|
||||
ASMJIT_INST_1x(rdsspq, Rdsspq, Gp) // CET_SS
|
||||
ASMJIT_INST_2x(wrssd, Wrssd, Gp, Gp) // CET_SS
|
||||
ASMJIT_INST_2x(wrssd, Wrssd, Mem, Gp) // CET_SS
|
||||
ASMJIT_INST_2x(wrssq, Wrssq, Gp, Gp) // CET_SS
|
||||
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_1x(vmptrld, Vmptrld, 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_0x(vmresume, Vmresume) // VMX
|
||||
ASMJIT_INST_2x(vmwrite, Vmwrite, Gp, Mem) // VMX
|
||||
ASMJIT_INST_2x(vmwrite, Vmwrite, Gp, Gp) // 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(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(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, Mem) // AVX512_F{kz|b64}
|
||||
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(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, Mem, 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_4x(vpblendd, Vpblendd, Vec, Vec, Vec, 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, Mem, Vec) // 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, Mem) // AVX2 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(vpbroadcastmw2d, Vpbroadcastmw2d, Vec, KReg) // AVX512_CD
|
||||
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, Gp) // AVX512_F{kz}
|
||||
@@ -3175,14 +3212,20 @@ public:
|
||||
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, 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, Mem) // 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(vpshldvw, Vpshldvw, Vec, Vec, Vec) // 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, 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, Mem) // 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(iretd, Iretd) // ANY [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, 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.
|
||||
@@ -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_0x(ret, Ret)
|
||||
ASMJIT_INST_1x(ret, Ret, Imm)
|
||||
ASMJIT_INST_0x(lret, Lret)
|
||||
ASMJIT_INST_1x(lret, Lret, Imm)
|
||||
ASMJIT_INST_0x(retf, Retf)
|
||||
ASMJIT_INST_1x(retf, Retf, Imm)
|
||||
ASMJIT_INST_0x(xlatb, Xlatb) // ANY [IMPLICIT]
|
||||
|
||||
//! \}
|
||||
@@ -3918,10 +3960,20 @@ struct EmitterImplicitT : public EmitterExplicitT<This> {
|
||||
//! \name XSAVE Instructions
|
||||
//! \{
|
||||
|
||||
// TODO: xrstor and xsave don't have explicit variants yet.
|
||||
|
||||
//! \cond
|
||||
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
|
||||
|
||||
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
|
||||
//! \{
|
||||
|
||||
@@ -3962,9 +4025,9 @@ struct EmitterImplicitT : public EmitterExplicitT<This> {
|
||||
ASMJIT_INST_0x(rdmsr, Rdmsr) // ANY [IMPLICIT]
|
||||
ASMJIT_INST_0x(rdpmc, Rdpmc) // ANY [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(sysret64, Sysret64) // X64 [IMPLICIT]
|
||||
ASMJIT_INST_0x(sysretq, Sysretq) // X64 [IMPLICIT]
|
||||
ASMJIT_INST_0x(wrmsr, Wrmsr) // ANY [IMPLICIT]
|
||||
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 {
|
||||
switch (size) {
|
||||
case 1 : return "byte ";
|
||||
case 2 : return "word ";
|
||||
case 4 : return "dword ";
|
||||
case 6 : return "fword ";
|
||||
case 8 : return "qword ";
|
||||
case 10: return "tbyte ";
|
||||
case 16: return "oword ";
|
||||
case 32: return "yword ";
|
||||
case 64: return "zword ";
|
||||
case 1 : return "byte ptr ";
|
||||
case 2 : return "word ptr ";
|
||||
case 4 : return "dword ptr ";
|
||||
case 6 : return "fword ptr ";
|
||||
case 8 : return "qword ptr ";
|
||||
case 10: return "tbyte ptr ";
|
||||
case 16: return "xmmword ptr ";
|
||||
case 32: return "ymmword ptr ";
|
||||
case 64: return "zmmword ptr ";
|
||||
default: return "";
|
||||
}
|
||||
}
|
||||
@@ -835,6 +835,17 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction(
|
||||
|
||||
// Format instruction options and instruction mnemonic.
|
||||
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.
|
||||
if (options & Inst::kOptionShortForm) ASMJIT_PROPAGATE(sb.append("short "));
|
||||
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));
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -121,6 +121,7 @@ struct Inst : public BaseInst {
|
||||
kIdCli, //!< Instruction 'cli'.
|
||||
kIdClrssbsy, //!< Instruction 'clrssbsy' {CET_SS}.
|
||||
kIdClts, //!< Instruction 'clts'.
|
||||
kIdClui, //!< Instruction 'clui' {UINTR} (X64).
|
||||
kIdClwb, //!< Instruction 'clwb' {CLWB}.
|
||||
kIdClzero, //!< Instruction 'clzero' {CLZERO}.
|
||||
kIdCmc, //!< Instruction 'cmc'.
|
||||
@@ -315,6 +316,7 @@ struct Inst : public BaseInst {
|
||||
kIdHaddpd, //!< Instruction 'haddpd' {SSE3}.
|
||||
kIdHaddps, //!< Instruction 'haddps' {SSE3}.
|
||||
kIdHlt, //!< Instruction 'hlt'.
|
||||
kIdHreset, //!< Instruction 'hreset' {HRESET}.
|
||||
kIdHsubpd, //!< Instruction 'hsubpd' {SSE3}.
|
||||
kIdHsubps, //!< Instruction 'hsubps' {SSE3}.
|
||||
kIdIdiv, //!< Instruction 'idiv'.
|
||||
@@ -338,7 +340,6 @@ struct Inst : public BaseInst {
|
||||
kIdIret, //!< Instruction 'iret'.
|
||||
kIdIretd, //!< Instruction 'iretd'.
|
||||
kIdIretq, //!< Instruction 'iretq' (X64).
|
||||
kIdIretw, //!< Instruction 'iretw'.
|
||||
kIdJa, //!< Instruction 'ja'.
|
||||
kIdJae, //!< Instruction 'jae'.
|
||||
kIdJb, //!< Instruction 'jb'.
|
||||
@@ -445,7 +446,6 @@ struct Inst : public BaseInst {
|
||||
kIdLoop, //!< Instruction 'loop'.
|
||||
kIdLoope, //!< Instruction 'loope'.
|
||||
kIdLoopne, //!< Instruction 'loopne'.
|
||||
kIdLret, //!< Instruction 'lret'.
|
||||
kIdLsl, //!< Instruction 'lsl'.
|
||||
kIdLss, //!< Instruction 'lss'.
|
||||
kIdLtr, //!< Instruction 'ltr'.
|
||||
@@ -716,6 +716,7 @@ struct Inst : public BaseInst {
|
||||
kIdRdtsc, //!< Instruction 'rdtsc' {RDTSC}.
|
||||
kIdRdtscp, //!< Instruction 'rdtscp' {RDTSCP}.
|
||||
kIdRet, //!< Instruction 'ret'.
|
||||
kIdRetf, //!< Instruction 'retf'.
|
||||
kIdRmpadjust, //!< Instruction 'rmpadjust' {SNP} (X64).
|
||||
kIdRmpupdate, //!< Instruction 'rmpupdate' {SNP} (X64).
|
||||
kIdRol, //!< Instruction 'rol'.
|
||||
@@ -736,6 +737,7 @@ struct Inst : public BaseInst {
|
||||
kIdSaveprevssp, //!< Instruction 'saveprevssp' {CET_SS}.
|
||||
kIdSbb, //!< Instruction 'sbb'.
|
||||
kIdScas, //!< Instruction 'scas'.
|
||||
kIdSenduipi, //!< Instruction 'senduipi' {UINTR} (X64).
|
||||
kIdSerialize, //!< Instruction 'serialize' {SERIALIZE}.
|
||||
kIdSeta, //!< Instruction 'seta'.
|
||||
kIdSetae, //!< Instruction 'setae'.
|
||||
@@ -803,6 +805,7 @@ struct Inst : public BaseInst {
|
||||
kIdStos, //!< Instruction 'stos'.
|
||||
kIdStr, //!< Instruction 'str'.
|
||||
kIdSttilecfg, //!< Instruction 'sttilecfg' {AMX_TILE} (X64).
|
||||
kIdStui, //!< Instruction 'stui' {UINTR} (X64).
|
||||
kIdSub, //!< Instruction 'sub'.
|
||||
kIdSubpd, //!< Instruction 'subpd' {SSE2}.
|
||||
kIdSubps, //!< Instruction 'subps' {SSE}.
|
||||
@@ -812,9 +815,9 @@ struct Inst : public BaseInst {
|
||||
kIdSyscall, //!< Instruction 'syscall' (X64).
|
||||
kIdSysenter, //!< Instruction 'sysenter'.
|
||||
kIdSysexit, //!< Instruction 'sysexit'.
|
||||
kIdSysexit64, //!< Instruction 'sysexit64'.
|
||||
kIdSysexitq, //!< Instruction 'sysexitq'.
|
||||
kIdSysret, //!< Instruction 'sysret' (X64).
|
||||
kIdSysret64, //!< Instruction 'sysret64' (X64).
|
||||
kIdSysretq, //!< Instruction 'sysretq' (X64).
|
||||
kIdT1mskc, //!< Instruction 't1mskc' {TBM}.
|
||||
kIdTdpbf16ps, //!< Instruction 'tdpbf16ps' {AMX_BF16} (X64).
|
||||
kIdTdpbssd, //!< Instruction 'tdpbssd' {AMX_INT8} (X64).
|
||||
@@ -822,6 +825,7 @@ struct Inst : public BaseInst {
|
||||
kIdTdpbusd, //!< Instruction 'tdpbusd' {AMX_INT8} (X64).
|
||||
kIdTdpbuud, //!< Instruction 'tdpbuud' {AMX_INT8} (X64).
|
||||
kIdTest, //!< Instruction 'test'.
|
||||
kIdTestui, //!< Instruction 'testui' {UINTR} (X64).
|
||||
kIdTileloadd, //!< Instruction 'tileloadd' {AMX_TILE} (X64).
|
||||
kIdTileloaddt1, //!< Instruction 'tileloaddt1' {AMX_TILE} (X64).
|
||||
kIdTilerelease, //!< Instruction 'tilerelease' {AMX_TILE} (X64).
|
||||
@@ -835,6 +839,7 @@ struct Inst : public BaseInst {
|
||||
kIdUd0, //!< Instruction 'ud0'.
|
||||
kIdUd1, //!< Instruction 'ud1'.
|
||||
kIdUd2, //!< Instruction 'ud2'.
|
||||
kIdUiret, //!< Instruction 'uiret' {UINTR} (X64).
|
||||
kIdUmonitor, //!< Instruction 'umonitor' {WAITPKG}.
|
||||
kIdUmwait, //!< Instruction 'umwait' {WAITPKG}.
|
||||
kIdUnpckhpd, //!< Instruction 'unpckhpd' {SSE2}.
|
||||
@@ -863,12 +868,8 @@ struct Inst : public BaseInst {
|
||||
kIdVandnps, //!< Instruction 'vandnps' {AVX|AVX512_DQ+VL}.
|
||||
kIdVandpd, //!< Instruction 'vandpd' {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}.
|
||||
kIdVblendmps, //!< Instruction 'vblendmps' {AVX512_F+VL}.
|
||||
kIdVblendmq, //!< Instruction 'vblendmq' {AVX512_F+VL}.
|
||||
kIdVblendmw, //!< Instruction 'vblendmw' {AVX512_BW+VL}.
|
||||
kIdVblendpd, //!< Instruction 'vblendpd' {AVX}.
|
||||
kIdVblendps, //!< Instruction 'vblendps' {AVX}.
|
||||
kIdVblendvpd, //!< Instruction 'vblendvpd' {AVX}.
|
||||
@@ -1189,12 +1190,16 @@ struct Inst : public BaseInst {
|
||||
kIdVpavgb, //!< Instruction 'vpavgb' {AVX|AVX2|AVX512_BW+VL}.
|
||||
kIdVpavgw, //!< Instruction 'vpavgw' {AVX|AVX2|AVX512_BW+VL}.
|
||||
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}.
|
||||
kIdVpblendw, //!< Instruction 'vpblendw' {AVX|AVX2}.
|
||||
kIdVpbroadcastb, //!< Instruction 'vpbroadcastb' {AVX2|AVX512_BW+VL}.
|
||||
kIdVpbroadcastd, //!< Instruction 'vpbroadcastd' {AVX2|AVX512_F+VL}.
|
||||
kIdVpbroadcastmb2d, //!< Instruction 'vpbroadcastmb2d' {AVX512_CDI+VL}.
|
||||
kIdVpbroadcastmb2q, //!< Instruction 'vpbroadcastmb2q' {AVX512_CDI+VL}.
|
||||
kIdVpbroadcastmw2d, //!< Instruction 'vpbroadcastmw2d' {AVX512_CDI+VL}.
|
||||
kIdVpbroadcastq, //!< Instruction 'vpbroadcastq' {AVX2|AVX512_F+VL}.
|
||||
kIdVpbroadcastw, //!< Instruction 'vpbroadcastw' {AVX2|AVX512_BW+VL}.
|
||||
kIdVpclmulqdq, //!< Instruction 'vpclmulqdq' {AVX|AVX512_F+VL & PCLMULQDQ|VPCLMULQDQ}.
|
||||
@@ -1606,7 +1611,8 @@ struct Inst : public BaseInst {
|
||||
|
||||
//! Instruction options.
|
||||
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).
|
||||
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).
|
||||
|
||||
@@ -1180,6 +1180,46 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera
|
||||
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: {
|
||||
// Special case for 'vmaskmovpd|vmaskmovps|vpmaskmovd|vpmaskmovq' instructions.
|
||||
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).
|
||||
kEncodingX86I_xAX, //!< X86 [I] (implicit or explicit '?AX' form).
|
||||
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_GPB, //!< X86 [M] (handles single-byte size).
|
||||
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_EDX_EAX, //!< X86 [M] (memory operand only, followed by implicit <edx> and <eax>).
|
||||
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_FromM, //!< X86 [R] - which specifies memory address.
|
||||
@@ -121,7 +123,8 @@ enum EncodingId : uint32_t {
|
||||
kEncodingExtRm_XMM0, //!< EXT [RM<XMM0>].
|
||||
kEncodingExtRm_ZDI, //!< EXT [RM<ZDI>].
|
||||
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_P, //!< EXT [RM|RI] (propagates 66H if the instruction uses XMM register).
|
||||
kEncodingExtRmi, //!< EXT [RMI].
|
||||
@@ -142,13 +145,15 @@ enum EncodingId : uint32_t {
|
||||
kEncodingVexM, //!< VEX|EVEX [M].
|
||||
kEncodingVexM_VM, //!< VEX|EVEX [M] (propagates VEX|EVEX.L, VSIB support).
|
||||
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_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_ZDI, //!< VEX|EVEX [RM<ZDI>].
|
||||
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_Narrow, //!< VEX|EVEX [RM] (the destination vector size is narrowed).
|
||||
kEncodingVexRm_Lx_Bcst, //!< VEX|EVEX [RM] (can handle broadcast r32/r64).
|
||||
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).
|
||||
@@ -159,11 +164,14 @@ enum EncodingId : uint32_t {
|
||||
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_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).
|
||||
kEncodingVexRvmr, //!< VEX|EVEX [RVMR].
|
||||
kEncodingVexRvmr_Lx, //!< VEX|EVEX [RVMR] (propagates VEX|EVEX.L if YMM used).
|
||||
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_KEvex, //!< VEX|EVEX [RVMI] (forces EVEX prefix if K register is used on destination).
|
||||
kEncodingVexRmv, //!< VEX|EVEX [RMV].
|
||||
kEncodingVexRmv_Wx, //!< VEX|EVEX [RMV] (propagates VEX|EVEX.W if GPQ used).
|
||||
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).
|
||||
kEncodingVexRvmVmi, //!< VEX|EVEX [RVM|VMI].
|
||||
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_Wx, //!< VEX|EVEX [VM] (propagates VEX|EVEX.W if GPQ used).
|
||||
kEncodingVexVmi, //!< VEX|EVEX [VMI].
|
||||
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).
|
||||
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_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).
|
||||
@@ -244,6 +253,7 @@ struct RWInfo {
|
||||
kCategoryMovabs,
|
||||
kCategoryImul,
|
||||
kCategoryMovh64,
|
||||
kCategoryPunpcklxx,
|
||||
kCategoryVmaskmov,
|
||||
kCategoryVmovddup,
|
||||
kCategoryVmovmskpd,
|
||||
|
||||
@@ -253,7 +253,7 @@ struct Opcode {
|
||||
// instructions that use OPCODE+MOD/RM where both values in Mod/RM
|
||||
// are part of the opcode.
|
||||
|
||||
kModRM_Shift = 10,
|
||||
kModRM_Shift = 13,
|
||||
kModRM_Mask = 0x7u << kModRM_Shift,
|
||||
|
||||
kModRM__ = 0x0u,
|
||||
@@ -432,6 +432,10 @@ struct Opcode {
|
||||
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).
|
||||
ASMJIT_INLINE uint32_t extractModO() const noexcept {
|
||||
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(zmmA, zmmB, zmmC);
|
||||
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, anyptr_gpC);
|
||||
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(zmmA, zmmB, zmmC);
|
||||
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, anyptr_gpB);
|
||||
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(zmmA, zmmB, zmmC);
|
||||
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, gzB);
|
||||
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, xmmB);
|
||||
e->vpbroadcastd(zmmA, anyptr_gpB);
|
||||
e->vpbroadcastmb2d(xmmA, kB);
|
||||
e->vpbroadcastmb2d(ymmA, kB);
|
||||
e->vpbroadcastmb2d(zmmA, kB);
|
||||
e->vpbroadcastmb2q(xmmA, kB);
|
||||
e->vpbroadcastmb2q(ymmA, kB);
|
||||
e->vpbroadcastmb2q(zmmA, kB);
|
||||
e->vpbroadcastmw2d(xmmA, kB);
|
||||
e->vpbroadcastmw2d(ymmA, kB);
|
||||
e->vpbroadcastmw2d(zmmA, kB);
|
||||
if (isX64) e->vpbroadcastq(xmmA, gzB);
|
||||
e->vpbroadcastq(xmmA, xmmB);
|
||||
e->vpbroadcastq(xmmA, anyptr_gpB);
|
||||
|
||||
@@ -933,32 +933,18 @@ class OSignature {
|
||||
const index = asmdb.x86.Utils.regIndexOf(k);
|
||||
if (index !== null && index !== -1) {
|
||||
const kind = asmdb.x86.Utils.regKindOf(k);
|
||||
if (indexKind !== kind) return false;
|
||||
if (indexKind !== kind)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Can merge...
|
||||
for (k in bf) af[k] = true;
|
||||
for (k in bf)
|
||||
af[k] = 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() {
|
||||
var s = "";
|
||||
var flags = this.flags;
|
||||
@@ -1124,11 +1110,6 @@ class ISignature extends Array {
|
||||
this.implicit = 0; // Number of implicit operands.
|
||||
}
|
||||
|
||||
simplify() {
|
||||
for (var i = 0; i < this.length; i++)
|
||||
this[i].simplify();
|
||||
}
|
||||
|
||||
opEquals(other) {
|
||||
const len = this.length;
|
||||
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() {
|
||||
for (var i = 0; i < this.length; i++) {
|
||||
var row = this[i];
|
||||
var j = i + 1;
|
||||
while (j < this.length) {
|
||||
if (row.mergeWith(this[j])) {
|
||||
this.splice(j, 1);
|
||||
continue;
|
||||
var didSomething = true;
|
||||
while (didSomething) {
|
||||
didSomething = false;
|
||||
for (var i = 0; i < this.length; i++) {
|
||||
var row = this[i];
|
||||
var j = i + 1;
|
||||
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"))
|
||||
break;
|
||||
|
||||
if (reg === "r8") reg = "r8lo";
|
||||
if (reg === "seg") reg = "sreg";
|
||||
if (reg === "st(i)") reg = "st";
|
||||
if (reg === "st(0)") reg = "st0";
|
||||
@@ -1571,6 +1551,46 @@ class InstSignatureTable extends core.Task {
|
||||
|
||||
const seg = iop.memSeg;
|
||||
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 === "es") op.flags.memES = 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; }
|
||||
}
|
||||
else if (reg) {
|
||||
op.flags[reg] = true;
|
||||
if (reg === "r8lo") op.flags.r8hi = true;
|
||||
if (reg == "r8") {
|
||||
op.flags["r8lo"] = true;
|
||||
op.flags["r8hi"] = true;
|
||||
}
|
||||
else {
|
||||
op.flags[reg] = true;
|
||||
}
|
||||
}
|
||||
if (mem) {
|
||||
op.flags[mem] = true;
|
||||
// Exception: Allow LEA to use any memory size.
|
||||
if (inst.name === "lea") MapUtils.add(op.flags, MemOp);
|
||||
// HACK: Allow LEA to use any memory size.
|
||||
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 (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))
|
||||
signatures.calcImplicitMemSize();
|
||||
|
||||
signatures.simplify();
|
||||
signatures.compact();
|
||||
|
||||
signatures.simplify();
|
||||
signatures.compact();
|
||||
|
||||
return signatures;
|
||||
}
|
||||
}
|
||||
@@ -1745,6 +1773,9 @@ class InstRWInfoTable extends core.Task {
|
||||
"movabs" : "Movabs",
|
||||
"movhpd" : "Movh64",
|
||||
"movhps" : "Movh64",
|
||||
"punpcklbw" : "Punpcklxx",
|
||||
"punpckldq" : "Punpcklxx",
|
||||
"punpcklwd" : "Punpcklxx",
|
||||
"vmaskmovpd": "Vmaskmov",
|
||||
"vmaskmovps": "Vmaskmov",
|
||||
"vmovddup" : "Vmovddup",
|
||||
@@ -2153,9 +2184,14 @@ class InstRWInfoTable extends core.Task {
|
||||
if (category === null)
|
||||
category = c;
|
||||
else if (category !== c) {
|
||||
// Special cases.
|
||||
if (dbInst.name === "mov" || dbInst.name === "vmovddup")
|
||||
return "None"; // Special case
|
||||
return StringUtils.capitalize(dbInst.name); // Special case.
|
||||
return "None";
|
||||
|
||||
if (/^(punpcklbw|punpckldq|punpcklwd)$/.test(dbInst.name))
|
||||
return "None";
|
||||
|
||||
return StringUtils.capitalize(dbInst.name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user