mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 20:44:37 +03:00
Added support for more X86 extensions (AMX, AVX512_VP2INTERSECT, MCOMMIT, RDPRU, SERIALIZE, SNP, TSXLDTRK)
This commit is contained in:
@@ -44,7 +44,11 @@ TODO
|
|||||||
----
|
----
|
||||||
|
|
||||||
* [ ] Core:
|
* [ ] Core:
|
||||||
* [ ] Add support for user external buffers in CodeHolder.
|
* [ ] Add support for user external buffers in CodeBuffer / CodeHolder.
|
||||||
|
* [ ] Register allocator doesn't understand register pairs, affected instructions:
|
||||||
|
* [ ] v4fmaddps, v4fmaddss, v4fnmaddps, v4fnmaddss
|
||||||
|
* [ ] vp4dpwssd, vp4dpwssds
|
||||||
|
* [ ] vp2intersectd, vp2intersectq
|
||||||
* [ ] Ports:
|
* [ ] Ports:
|
||||||
* [ ] ARM/Thumb/AArch64 support.
|
* [ ] ARM/Thumb/AArch64 support.
|
||||||
|
|
||||||
|
|||||||
@@ -789,7 +789,7 @@ Error BaseBuilder::comment(const char* data, size_t size) {
|
|||||||
// [asmjit::BaseBuilder - Serialize]
|
// [asmjit::BaseBuilder - Serialize]
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
Error BaseBuilder::serialize(BaseEmitter* dst) {
|
Error BaseBuilder::serializeTo(BaseEmitter* dst) {
|
||||||
Error err = kErrorOk;
|
Error err = kErrorOk;
|
||||||
BaseNode* node_ = _firstNode;
|
BaseNode* node_ = _firstNode;
|
||||||
|
|
||||||
|
|||||||
@@ -357,7 +357,7 @@ public:
|
|||||||
//! Although not explicitly required the emitter will most probably be of
|
//! Although not explicitly required the emitter will most probably be of
|
||||||
//! Assembler type. The reason is that there is no known use of serializing
|
//! Assembler type. The reason is that there is no known use of serializing
|
||||||
//! nodes held by Builder/Compiler into another Builder-like emitter.
|
//! nodes held by Builder/Compiler into another Builder-like emitter.
|
||||||
ASMJIT_API Error serialize(BaseEmitter* dst);
|
ASMJIT_API Error serializeTo(BaseEmitter* dst);
|
||||||
|
|
||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
@@ -370,6 +370,11 @@ public:
|
|||||||
//! \}
|
//! \}
|
||||||
|
|
||||||
#ifndef ASMJIT_NO_DEPRECATED
|
#ifndef ASMJIT_NO_DEPRECATED
|
||||||
|
ASMJIT_DEPRECATED("Use serializeTo() instead, serialize() is now also an instruction.")
|
||||||
|
inline Error serialize(BaseEmitter* dst) {
|
||||||
|
return serializeTo(dst);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef ASMJIT_NO_LOGGING
|
#ifndef ASMJIT_NO_LOGGING
|
||||||
ASMJIT_DEPRECATED("Use Formatter::formatNodeList(sb, formatFlags, builder)")
|
ASMJIT_DEPRECATED("Use Formatter::formatNodeList(sb, formatFlags, builder)")
|
||||||
inline Error dump(String& sb, uint32_t formatFlags = 0) const noexcept {
|
inline Error dump(String& sb, uint32_t formatFlags = 0) const noexcept {
|
||||||
|
|||||||
@@ -674,7 +674,7 @@ public:
|
|||||||
kTypeIP = 15,
|
kTypeIP = 15,
|
||||||
//! Start of platform dependent register types (must be honored).
|
//! Start of platform dependent register types (must be honored).
|
||||||
kTypeCustom = 16,
|
kTypeCustom = 16,
|
||||||
//! Maximum possible register id of all architectures.
|
//! Maximum possible register type value.
|
||||||
kTypeMax = 31
|
kTypeMax = 31
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -669,6 +669,13 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(uint32_t instId, const Operand_& o0, c
|
|||||||
// [Encoding Scope]
|
// [Encoding Scope]
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// How it works? Each case here represents a unique encoding of a group of
|
||||||
|
// instructions, which is handled separately. The handlers check instruction
|
||||||
|
// signature, possibly register types, etc, and process this information by
|
||||||
|
// writing some bits to opcode, opReg/rbReg, immValue/immSize, etc, and then
|
||||||
|
// at the end of the sequence it uses goto to jump into a lower level handler,
|
||||||
|
// that actually encodes the instruction.
|
||||||
|
|
||||||
switch (instInfo->_encoding) {
|
switch (instInfo->_encoding) {
|
||||||
case InstDB::kEncodingNone:
|
case InstDB::kEncodingNone:
|
||||||
goto EmitDone;
|
goto EmitDone;
|
||||||
@@ -854,6 +861,32 @@ CaseX86M_GPB_MulDiv:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case InstDB::kEncodingX86R_FromM:
|
||||||
|
if (isign3 == ENC_OPS1(Mem)) {
|
||||||
|
rmRel = &o0;
|
||||||
|
rbReg = o0.id();
|
||||||
|
goto EmitX86RFromM;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InstDB::kEncodingX86R32_EDX_EAX:
|
||||||
|
// Explicit form: R32, EDX, EAX.
|
||||||
|
if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
|
||||||
|
if (!Reg::isGpd(o1, Gp::kIdDx) || !Reg::isGpd(o2, Gp::kIdAx))
|
||||||
|
goto InvalidInstruction;
|
||||||
|
rbReg = o0.id();
|
||||||
|
goto EmitX86R;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Implicit form: R32.
|
||||||
|
if (isign3 == ENC_OPS1(Reg)) {
|
||||||
|
if (!Reg::isGpd(o0))
|
||||||
|
goto InvalidInstruction;
|
||||||
|
rbReg = o0.id();
|
||||||
|
goto EmitX86R;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case InstDB::kEncodingX86R_Native:
|
case InstDB::kEncodingX86R_Native:
|
||||||
if (isign3 == ENC_OPS1(Reg)) {
|
if (isign3 == ENC_OPS1(Reg)) {
|
||||||
rbReg = o0.id();
|
rbReg = o0.id();
|
||||||
@@ -2767,6 +2800,10 @@ CaseExtRm:
|
|||||||
case InstDB::kEncodingVexOp:
|
case InstDB::kEncodingVexOp:
|
||||||
goto EmitVexEvexOp;
|
goto EmitVexEvexOp;
|
||||||
|
|
||||||
|
case InstDB::kEncodingVexOpMod:
|
||||||
|
rbReg = 0;
|
||||||
|
goto EmitVexEvexR;
|
||||||
|
|
||||||
case InstDB::kEncodingVexKmov:
|
case InstDB::kEncodingVexKmov:
|
||||||
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
||||||
opReg = o0.id();
|
opReg = o0.id();
|
||||||
@@ -3007,6 +3044,33 @@ CaseVexRvm_R:
|
|||||||
goto CaseVexRvm;
|
goto CaseVexRvm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case InstDB::kEncodingVexRvm_Lx_2xK: {
|
||||||
|
if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
|
||||||
|
// Two registers are encoded as a single register.
|
||||||
|
// - First K register must be even.
|
||||||
|
// - Second K register must be first+1.
|
||||||
|
if ((o0.id() & 1) != 0 || o0.id() + 1 != o1.id())
|
||||||
|
goto InvalidPhysId;
|
||||||
|
|
||||||
|
const Operand_& o3 = opExt[EmitterUtils::kOp3];
|
||||||
|
|
||||||
|
opcode |= x86OpcodeLBySize(o2.size());
|
||||||
|
opReg = x86PackRegAndVvvvv(o0.id(), o2.id());
|
||||||
|
|
||||||
|
if (o3.isReg()) {
|
||||||
|
rbReg = o3.id();
|
||||||
|
goto EmitVexEvexR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o3.isMem()) {
|
||||||
|
rmRel = &o3;
|
||||||
|
goto EmitVexEvexM;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case InstDB::kEncodingVexRvmr_Lx: {
|
case InstDB::kEncodingVexRvmr_Lx: {
|
||||||
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
||||||
ASMJIT_FALLTHROUGH;
|
ASMJIT_FALLTHROUGH;
|
||||||
@@ -3598,6 +3662,49 @@ CaseVexVmi_AfterImm:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
// [AMX]
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
|
case InstDB::kEncodingAmxCfg:
|
||||||
|
if (isign3 == ENC_OPS1(Mem)) {
|
||||||
|
rmRel = &o0;
|
||||||
|
goto EmitVexEvexM;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InstDB::kEncodingAmxR:
|
||||||
|
if (isign3 == ENC_OPS1(Reg)) {
|
||||||
|
opReg = o0.id();
|
||||||
|
rbReg = 0;
|
||||||
|
goto EmitVexEvexR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InstDB::kEncodingAmxRm:
|
||||||
|
if (isign3 == ENC_OPS2(Reg, Mem)) {
|
||||||
|
opReg = o0.id();
|
||||||
|
rmRel = &o1;
|
||||||
|
goto EmitVexEvexM;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InstDB::kEncodingAmxMr:
|
||||||
|
if (isign3 == ENC_OPS2(Mem, Reg)) {
|
||||||
|
opReg = o1.id();
|
||||||
|
rmRel = &o0;
|
||||||
|
goto EmitVexEvexM;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InstDB::kEncodingAmxRmv:
|
||||||
|
if (isign3 == ENC_OPS3(Reg, Reg, Reg)) {
|
||||||
|
opReg = x86PackRegAndVvvvv(o0.id(), o2.id());
|
||||||
|
rbReg = o1.id();
|
||||||
|
goto EmitVexEvexR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
goto InvalidInstruction;
|
goto InvalidInstruction;
|
||||||
@@ -3628,6 +3735,10 @@ EmitX86Op:
|
|||||||
writer.emitImmediate(uint64_t(immValue), immSize);
|
writer.emitImmediate(uint64_t(immValue), immSize);
|
||||||
goto EmitDone;
|
goto EmitDone;
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// [Emit - X86 - Opcode + Reg]
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
EmitX86OpReg:
|
EmitX86OpReg:
|
||||||
// Emit mandatory instruction prefix.
|
// Emit mandatory instruction prefix.
|
||||||
writer.emitPP(opcode.v);
|
writer.emitPP(opcode.v);
|
||||||
@@ -3649,8 +3760,11 @@ EmitX86OpReg:
|
|||||||
writer.emitImmediate(uint64_t(immValue), immSize);
|
writer.emitImmediate(uint64_t(immValue), immSize);
|
||||||
goto EmitDone;
|
goto EmitDone;
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// [Emit - X86 - Opcode with implicit <mem> operand]
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
EmitX86OpImplicitMem:
|
EmitX86OpImplicitMem:
|
||||||
// NOTE: Don't change the emit order here, it's compatible with KeyStone/LLVM.
|
|
||||||
rmInfo = x86MemInfo[rmRel->as<Mem>().baseAndIndexTypes()];
|
rmInfo = x86MemInfo[rmRel->as<Mem>().baseAndIndexTypes()];
|
||||||
if (ASMJIT_UNLIKELY(rmRel->as<Mem>().hasOffset() || (rmInfo & kX86MemInfo_Index)))
|
if (ASMJIT_UNLIKELY(rmRel->as<Mem>().hasOffset() || (rmInfo & kX86MemInfo_Index)))
|
||||||
goto InvalidInstruction;
|
goto InvalidInstruction;
|
||||||
@@ -3667,19 +3781,26 @@ EmitX86OpImplicitMem:
|
|||||||
writer.emit8If(rex | kX86ByteRex, rex != 0);
|
writer.emit8If(rex | kX86ByteRex, rex != 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emit override prefixes.
|
||||||
writer.emitSegmentOverride(rmRel->as<Mem>().segmentId());
|
writer.emitSegmentOverride(rmRel->as<Mem>().segmentId());
|
||||||
writer.emitAddressOverride((rmInfo & _addressOverrideMask()) != 0);
|
writer.emitAddressOverride((rmInfo & _addressOverrideMask()) != 0);
|
||||||
|
|
||||||
// Emit instruction opcodes.
|
// Emit instruction opcodes.
|
||||||
writer.emitMMAndOpcode(opcode.v);
|
writer.emitMMAndOpcode(opcode.v);
|
||||||
|
|
||||||
|
// Emit immediate value.
|
||||||
writer.emitImmediate(uint64_t(immValue), immSize);
|
writer.emitImmediate(uint64_t(immValue), immSize);
|
||||||
goto EmitDone;
|
goto EmitDone;
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// [Emit - X86 - Opcode /r - register]
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
EmitX86R:
|
EmitX86R:
|
||||||
// Mandatory instruction prefix.
|
// Mandatory instruction prefix.
|
||||||
writer.emitPP(opcode.v);
|
writer.emitPP(opcode.v);
|
||||||
|
|
||||||
// Rex prefix (64-bit only).
|
// Emit REX prefix (64-bit only).
|
||||||
{
|
{
|
||||||
uint32_t rex = opcode.extractRex(options) |
|
uint32_t rex = opcode.extractRex(options) |
|
||||||
((opReg & 0x08) >> 1) | // REX.R (0x04).
|
((opReg & 0x08) >> 1) | // REX.R (0x04).
|
||||||
@@ -3694,32 +3815,80 @@ EmitX86R:
|
|||||||
rbReg &= 0x07;
|
rbReg &= 0x07;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instruction opcodes.
|
// Emit instruction opcodes.
|
||||||
writer.emitMMAndOpcode(opcode.v);
|
writer.emitMMAndOpcode(opcode.v);
|
||||||
// ModR.
|
|
||||||
|
// Emit ModR.
|
||||||
writer.emit8(x86EncodeMod(3, opReg, rbReg));
|
writer.emit8(x86EncodeMod(3, opReg, rbReg));
|
||||||
|
// Emit immediate value.
|
||||||
|
|
||||||
writer.emitImmediate(uint64_t(immValue), immSize);
|
writer.emitImmediate(uint64_t(immValue), immSize);
|
||||||
goto EmitDone;
|
goto EmitDone;
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// [Emit - X86 - Opcode /r - memory base]
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
EmitX86RFromM:
|
||||||
|
rmInfo = x86MemInfo[rmRel->as<Mem>().baseAndIndexTypes()];
|
||||||
|
if (ASMJIT_UNLIKELY(rmRel->as<Mem>().hasOffset() || (rmInfo & kX86MemInfo_Index)))
|
||||||
|
goto InvalidInstruction;
|
||||||
|
|
||||||
|
// Emit mandatory instruction prefix.
|
||||||
|
writer.emitPP(opcode.v);
|
||||||
|
|
||||||
|
// Emit REX prefix (64-bit only).
|
||||||
|
{
|
||||||
|
uint32_t rex = opcode.extractRex(options) |
|
||||||
|
((opReg & 0x08) >> 1) | // REX.R (0x04).
|
||||||
|
((rbReg ) >> 3) ; // REX.B (0x01).
|
||||||
|
|
||||||
|
if (ASMJIT_UNLIKELY(x86IsRexInvalid(rex)))
|
||||||
|
goto InvalidRexPrefix;
|
||||||
|
rex &= ~kX86ByteInvalidRex & 0xFF;
|
||||||
|
writer.emit8If(rex | kX86ByteRex, rex != 0);
|
||||||
|
|
||||||
|
opReg &= 0x07;
|
||||||
|
rbReg &= 0x07;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit override prefixes.
|
||||||
|
writer.emitSegmentOverride(rmRel->as<Mem>().segmentId());
|
||||||
|
writer.emitAddressOverride((rmInfo & _addressOverrideMask()) != 0);
|
||||||
|
|
||||||
|
// Emit instruction opcodes.
|
||||||
|
writer.emitMMAndOpcode(opcode.v);
|
||||||
|
|
||||||
|
// Emit ModR/M.
|
||||||
|
writer.emit8(x86EncodeMod(3, opReg, rbReg));
|
||||||
|
|
||||||
|
// Emit immediate value.
|
||||||
|
writer.emitImmediate(uint64_t(immValue), immSize);
|
||||||
|
goto EmitDone;
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// [Emit - X86 - Opcode /r - memory operand]
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
EmitX86M:
|
EmitX86M:
|
||||||
// `rmRel` operand must be memory.
|
// `rmRel` operand must be memory.
|
||||||
ASMJIT_ASSERT(rmRel != nullptr);
|
ASMJIT_ASSERT(rmRel != nullptr);
|
||||||
ASMJIT_ASSERT(rmRel->opType() == Operand::kOpMem);
|
ASMJIT_ASSERT(rmRel->opType() == Operand::kOpMem);
|
||||||
ASMJIT_ASSERT((opcode & Opcode::kCDSHL_Mask) == 0);
|
ASMJIT_ASSERT((opcode & Opcode::kCDSHL_Mask) == 0);
|
||||||
|
|
||||||
|
// Emit override prefixes.
|
||||||
rmInfo = x86MemInfo[rmRel->as<Mem>().baseAndIndexTypes()];
|
rmInfo = x86MemInfo[rmRel->as<Mem>().baseAndIndexTypes()];
|
||||||
writer.emitSegmentOverride(rmRel->as<Mem>().segmentId());
|
writer.emitSegmentOverride(rmRel->as<Mem>().segmentId());
|
||||||
|
|
||||||
memOpAOMark = writer.cursor();
|
memOpAOMark = writer.cursor();
|
||||||
writer.emitAddressOverride((rmInfo & _addressOverrideMask()) != 0);
|
writer.emitAddressOverride((rmInfo & _addressOverrideMask()) != 0);
|
||||||
|
|
||||||
// Mandatory instruction prefix.
|
// Emit mandatory instruction prefix.
|
||||||
writer.emitPP(opcode.v);
|
writer.emitPP(opcode.v);
|
||||||
|
|
||||||
|
// Emit REX prefix (64-bit only).
|
||||||
rbReg = rmRel->as<Mem>().baseId();
|
rbReg = rmRel->as<Mem>().baseId();
|
||||||
rxReg = rmRel->as<Mem>().indexId();
|
rxReg = rmRel->as<Mem>().indexId();
|
||||||
|
|
||||||
// REX prefix (64-bit only).
|
|
||||||
{
|
{
|
||||||
uint32_t rex;
|
uint32_t rex;
|
||||||
|
|
||||||
@@ -3738,8 +3907,9 @@ EmitX86M:
|
|||||||
opReg &= 0x07;
|
opReg &= 0x07;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Instruction opcodes.
|
// Emit instruction opcodes.
|
||||||
writer.emitMMAndOpcode(opcode.v);
|
writer.emitMMAndOpcode(opcode.v);
|
||||||
|
|
||||||
// ... Fall through ...
|
// ... Fall through ...
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -3754,25 +3924,28 @@ EmitModSib:
|
|||||||
relOffset = rmRel->as<Mem>().offsetLo32();
|
relOffset = rmRel->as<Mem>().offsetLo32();
|
||||||
|
|
||||||
uint32_t mod = x86EncodeMod(0, opReg, rbReg);
|
uint32_t mod = x86EncodeMod(0, opReg, rbReg);
|
||||||
if (rbReg == Gp::kIdSp) {
|
bool forceSIB = commonInfo->isTsibOp();
|
||||||
// [XSP|R12].
|
|
||||||
if (relOffset == 0) {
|
if (rbReg == Gp::kIdSp || forceSIB) {
|
||||||
|
// TSIB or [XSP|R12].
|
||||||
|
mod = (mod & 0xF8u) | 0x04u;
|
||||||
|
if (rbReg != Gp::kIdBp && relOffset == 0) {
|
||||||
writer.emit8(mod);
|
writer.emit8(mod);
|
||||||
writer.emit8(x86EncodeSib(0, 4, 4));
|
writer.emit8(x86EncodeSib(0, 4, rbReg));
|
||||||
}
|
}
|
||||||
// [XSP|R12 + DISP8|DISP32].
|
// TSIB or [XSP|R12 + DISP8|DISP32].
|
||||||
else {
|
else {
|
||||||
uint32_t cdShift = (opcode & Opcode::kCDSHL_Mask) >> Opcode::kCDSHL_Shift;
|
uint32_t cdShift = (opcode & Opcode::kCDSHL_Mask) >> Opcode::kCDSHL_Shift;
|
||||||
int32_t cdOffset = relOffset >> cdShift;
|
int32_t cdOffset = relOffset >> cdShift;
|
||||||
|
|
||||||
if (Support::isInt8(cdOffset) && relOffset == int32_t(uint32_t(cdOffset) << cdShift)) {
|
if (Support::isInt8(cdOffset) && relOffset == int32_t(uint32_t(cdOffset) << cdShift)) {
|
||||||
writer.emit8(mod + 0x40); // <- MOD(1, opReg, rbReg).
|
writer.emit8(mod + 0x40); // <- MOD(1, opReg, rbReg).
|
||||||
writer.emit8(x86EncodeSib(0, 4, 4));
|
writer.emit8(x86EncodeSib(0, 4, rbReg));
|
||||||
writer.emit8(cdOffset & 0xFF);
|
writer.emit8(cdOffset & 0xFF);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
writer.emit8(mod + 0x80); // <- MOD(2, opReg, rbReg).
|
writer.emit8(mod + 0x80); // <- MOD(2, opReg, rbReg).
|
||||||
writer.emit8(x86EncodeSib(0, 4, 4));
|
writer.emit8(x86EncodeSib(0, 4, rbReg));
|
||||||
writer.emit32uLE(uint32_t(relOffset));
|
writer.emit32uLE(uint32_t(relOffset));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4144,7 +4317,7 @@ EmitFpuOp:
|
|||||||
goto EmitDone;
|
goto EmitDone;
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// [Emit - VEX / EVEX]
|
// [Emit - VEX|EVEX]
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
EmitVexEvexOp:
|
EmitVexEvexOp:
|
||||||
@@ -4181,6 +4354,10 @@ EmitVexEvexOp:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// [Emit - VEX|EVEX - /r (Register)]
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
EmitVexEvexR:
|
EmitVexEvexR:
|
||||||
{
|
{
|
||||||
// Construct `x` - a complete EVEX|VEX prefix.
|
// Construct `x` - a complete EVEX|VEX prefix.
|
||||||
@@ -4288,6 +4465,10 @@ EmitVexEvexR:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// [Emit - VEX|EVEX - /r (Memory)]
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
EmitVexEvexM:
|
EmitVexEvexM:
|
||||||
ASMJIT_ASSERT(rmRel != nullptr);
|
ASMJIT_ASSERT(rmRel != nullptr);
|
||||||
ASMJIT_ASSERT(rmRel->opType() == Operand::kOpMem);
|
ASMJIT_ASSERT(rmRel->opType() == Operand::kOpMem);
|
||||||
@@ -4623,6 +4804,7 @@ EmitDone:
|
|||||||
ERROR_HANDLER(InvalidAddressIndex)
|
ERROR_HANDLER(InvalidAddressIndex)
|
||||||
ERROR_HANDLER(InvalidAddress64Bit)
|
ERROR_HANDLER(InvalidAddress64Bit)
|
||||||
ERROR_HANDLER(InvalidDisplacement)
|
ERROR_HANDLER(InvalidDisplacement)
|
||||||
|
ERROR_HANDLER(InvalidPhysId)
|
||||||
ERROR_HANDLER(InvalidSegment)
|
ERROR_HANDLER(InvalidSegment)
|
||||||
ERROR_HANDLER(InvalidImmediate)
|
ERROR_HANDLER(InvalidImmediate)
|
||||||
ERROR_HANDLER(OperandSizeMismatch)
|
ERROR_HANDLER(OperandSizeMismatch)
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ Error Builder::finalize() {
|
|||||||
Assembler a(_code);
|
Assembler a(_code);
|
||||||
a.addEncodingOptions(encodingOptions());
|
a.addEncodingOptions(encodingOptions());
|
||||||
a.addValidationOptions(validationOptions());
|
a.addValidationOptions(validationOptions());
|
||||||
return serialize(&a);
|
return serializeTo(&a);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ Error Compiler::finalize() {
|
|||||||
Assembler a(_code);
|
Assembler a(_code);
|
||||||
a.addEncodingOptions(encodingOptions());
|
a.addEncodingOptions(encodingOptions());
|
||||||
a.addValidationOptions(validationOptions());
|
a.addValidationOptions(validationOptions());
|
||||||
return serialize(&a);
|
return serializeTo(&a);
|
||||||
}
|
}
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// [asmjit::x86::Compiler - Events]
|
// [asmjit::x86::Compiler - Events]
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -259,7 +259,12 @@ ASMJIT_FAVOR_SIZE void detectCpu(CpuInfo& cpu) noexcept {
|
|||||||
if (bitTest(regs.ecx, 27)) features.add(Features::kMOVDIRI);
|
if (bitTest(regs.ecx, 27)) features.add(Features::kMOVDIRI);
|
||||||
if (bitTest(regs.ecx, 28)) features.add(Features::kMOVDIR64B);
|
if (bitTest(regs.ecx, 28)) features.add(Features::kMOVDIR64B);
|
||||||
if (bitTest(regs.ecx, 29)) features.add(Features::kENQCMD);
|
if (bitTest(regs.ecx, 29)) features.add(Features::kENQCMD);
|
||||||
|
if (bitTest(regs.edx, 14)) features.add(Features::kSERIALIZE);
|
||||||
|
if (bitTest(regs.edx, 16)) features.add(Features::kTSXLDTRK);
|
||||||
if (bitTest(regs.edx, 18)) features.add(Features::kPCONFIG);
|
if (bitTest(regs.edx, 18)) features.add(Features::kPCONFIG);
|
||||||
|
if (bitTest(regs.edx, 22)) features.add(Features::kAMX_BF16);
|
||||||
|
if (bitTest(regs.edx, 24)) features.add(Features::kAMX_TILE);
|
||||||
|
if (bitTest(regs.edx, 25)) features.add(Features::kAMX_INT8);
|
||||||
|
|
||||||
// Detect 'TSX' - Requires at least one of `HLE` and `RTM` features.
|
// Detect 'TSX' - Requires at least one of `HLE` and `RTM` features.
|
||||||
if (features.hasHLE() || features.hasRTM())
|
if (features.hasHLE() || features.hasRTM())
|
||||||
@@ -330,7 +335,7 @@ ASMJIT_FAVOR_SIZE void detectCpu(CpuInfo& cpu) noexcept {
|
|||||||
uint32_t i = maxId;
|
uint32_t i = maxId;
|
||||||
|
|
||||||
// The highest EAX that we understand.
|
// The highest EAX that we understand.
|
||||||
uint32_t kHighestProcessedEAX = 0x80000008u;
|
uint32_t kHighestProcessedEAX = 0x8000001Fu;
|
||||||
|
|
||||||
// Several CPUID calls are required to get the whole branc string. It's easy
|
// Several CPUID calls are required to get the whole branc string. It's easy
|
||||||
// to copy one DWORD at a time instead of performing a byte copy.
|
// to copy one DWORD at a time instead of performing a byte copy.
|
||||||
@@ -357,8 +362,9 @@ ASMJIT_FAVOR_SIZE void detectCpu(CpuInfo& cpu) noexcept {
|
|||||||
if (bitTest(regs.edx, 21)) features.add(Features::kFXSROPT);
|
if (bitTest(regs.edx, 21)) features.add(Features::kFXSROPT);
|
||||||
if (bitTest(regs.edx, 22)) features.add(Features::kMMX2);
|
if (bitTest(regs.edx, 22)) features.add(Features::kMMX2);
|
||||||
if (bitTest(regs.edx, 27)) features.add(Features::kRDTSCP);
|
if (bitTest(regs.edx, 27)) features.add(Features::kRDTSCP);
|
||||||
|
if (bitTest(regs.edx, 29)) features.add(Features::kPREFETCHW);
|
||||||
if (bitTest(regs.edx, 30)) features.add(Features::k3DNOW2, Features::kMMX2);
|
if (bitTest(regs.edx, 30)) features.add(Features::k3DNOW2, Features::kMMX2);
|
||||||
if (bitTest(regs.edx, 31)) features.add(Features::k3DNOW);
|
if (bitTest(regs.edx, 31)) features.add(Features::kPREFETCHW);
|
||||||
|
|
||||||
if (cpu.hasFeature(Features::kAVX)) {
|
if (cpu.hasFeature(Features::kAVX)) {
|
||||||
if (bitTest(regs.ecx, 11)) features.add(Features::kXOP);
|
if (bitTest(regs.ecx, 11)) features.add(Features::kXOP);
|
||||||
@@ -379,12 +385,22 @@ ASMJIT_FAVOR_SIZE void detectCpu(CpuInfo& cpu) noexcept {
|
|||||||
*brand++ = regs.ecx;
|
*brand++ = regs.ecx;
|
||||||
*brand++ = regs.edx;
|
*brand++ = regs.edx;
|
||||||
|
|
||||||
// Go directly to the last one.
|
// Go directly to the next one we are interested in.
|
||||||
if (i == 0x80000004u) i = 0x80000008u - 1;
|
if (i == 0x80000004u) i = 0x80000008u - 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x80000008u:
|
case 0x80000008u:
|
||||||
if (bitTest(regs.ebx, 0)) features.add(Features::kCLZERO);
|
if (bitTest(regs.ebx, 0)) features.add(Features::kCLZERO);
|
||||||
|
if (bitTest(regs.ebx, 0)) features.add(Features::kRDPRU);
|
||||||
|
if (bitTest(regs.ebx, 8)) features.add(Features::kMCOMMIT);
|
||||||
|
if (bitTest(regs.ebx, 9)) features.add(Features::kWBNOINVD);
|
||||||
|
|
||||||
|
// Go directly to the next one we are interested in.
|
||||||
|
i = 0x8000001Fu - 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x8000001Fu:
|
||||||
|
if (bitTest(regs.eax, 4)) features.add(Features::kSNP);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while (++i <= maxId);
|
} while (++i <= maxId);
|
||||||
|
|||||||
@@ -52,6 +52,9 @@ public:
|
|||||||
kADX, //!< CPU has ADX (multi-precision add-carry instruction extensions).
|
kADX, //!< CPU has ADX (multi-precision add-carry instruction extensions).
|
||||||
kAESNI, //!< CPU has AESNI (AES encode/decode instructions).
|
kAESNI, //!< CPU has AESNI (AES encode/decode instructions).
|
||||||
kALTMOVCR8, //!< CPU has LOCK MOV R<->CR0 (supports `MOV R<->CR8` via `LOCK MOV R<->CR0` in 32-bit mode) [AMD].
|
kALTMOVCR8, //!< CPU has LOCK MOV R<->CR0 (supports `MOV R<->CR8` via `LOCK MOV R<->CR0` in 32-bit mode) [AMD].
|
||||||
|
kAMX_BF16, //!< CPU has AMX_BF16 (advanced matrix extensions - BF16 instructions).
|
||||||
|
kAMX_INT8, //!< CPU has AMX_INT8 (advanced matrix extensions - INT8 instructions).
|
||||||
|
kAMX_TILE, //!< CPU has AMX_TILE (advanced matrix extensions).
|
||||||
kAVX, //!< CPU has AVX (advanced vector extensions).
|
kAVX, //!< CPU has AVX (advanced vector extensions).
|
||||||
kAVX2, //!< CPU has AVX2 (advanced vector extensions 2).
|
kAVX2, //!< CPU has AVX2 (advanced vector extensions 2).
|
||||||
kAVX512_4FMAPS, //!< CPU has AVX512_FMAPS (FMA packed single).
|
kAVX512_4FMAPS, //!< CPU has AVX512_FMAPS (FMA packed single).
|
||||||
@@ -98,6 +101,7 @@ public:
|
|||||||
kLAHFSAHF, //!< CPU has LAHF/SAHF (LAHF/SAHF in 64-bit mode) [X86_64].
|
kLAHFSAHF, //!< CPU has LAHF/SAHF (LAHF/SAHF in 64-bit mode) [X86_64].
|
||||||
kLWP, //!< CPU has LWP (lightweight profiling) [AMD].
|
kLWP, //!< CPU has LWP (lightweight profiling) [AMD].
|
||||||
kLZCNT, //!< CPU has LZCNT (LZCNT instruction).
|
kLZCNT, //!< CPU has LZCNT (LZCNT instruction).
|
||||||
|
kMCOMMIT, //!< CPU has MCOMMIT (MCOMMIT instruction).
|
||||||
kMMX, //!< CPU has MMX (MMX base instructions).
|
kMMX, //!< CPU has MMX (MMX base instructions).
|
||||||
kMMX2, //!< CPU has MMX2 (MMX extensions or MMX2).
|
kMMX2, //!< CPU has MMX2 (MMX extensions or MMX2).
|
||||||
kMONITOR, //!< CPU has MONITOR (MONITOR/MWAIT instructions).
|
kMONITOR, //!< CPU has MONITOR (MONITOR/MWAIT instructions).
|
||||||
@@ -116,16 +120,19 @@ public:
|
|||||||
kPREFETCHW, //!< CPU has PREFETCHW.
|
kPREFETCHW, //!< CPU has PREFETCHW.
|
||||||
kPREFETCHWT1, //!< CPU has PREFETCHWT1.
|
kPREFETCHWT1, //!< CPU has PREFETCHWT1.
|
||||||
kRDPID, //!< CPU has RDPID.
|
kRDPID, //!< CPU has RDPID.
|
||||||
|
kRDPRU, //!< CPU has RDPRU.
|
||||||
kRDRAND, //!< CPU has RDRAND.
|
kRDRAND, //!< CPU has RDRAND.
|
||||||
kRDSEED, //!< CPU has RDSEED.
|
kRDSEED, //!< CPU has RDSEED.
|
||||||
kRDTSC, //!< CPU has RDTSC.
|
kRDTSC, //!< CPU has RDTSC.
|
||||||
kRDTSCP, //!< CPU has RDTSCP.
|
kRDTSCP, //!< CPU has RDTSCP.
|
||||||
kRTM, //!< CPU has RTM.
|
kRTM, //!< CPU has RTM.
|
||||||
|
kSERIALIZE, //!< CPU has SERIALIZE.
|
||||||
kSHA, //!< CPU has SHA (SHA-1 and SHA-256 instructions).
|
kSHA, //!< CPU has SHA (SHA-1 and SHA-256 instructions).
|
||||||
kSKINIT, //!< CPU has SKINIT (SKINIT/STGI instructions) [AMD].
|
kSKINIT, //!< CPU has SKINIT (SKINIT/STGI instructions) [AMD].
|
||||||
kSMAP, //!< CPU has SMAP (supervisor-mode access prevention).
|
kSMAP, //!< CPU has SMAP (supervisor-mode access prevention).
|
||||||
kSMEP, //!< CPU has SMEP (supervisor-mode execution prevention).
|
kSMEP, //!< CPU has SMEP (supervisor-mode execution prevention).
|
||||||
kSMX, //!< CPU has SMX (safer mode extensions).
|
kSMX, //!< CPU has SMX (safer mode extensions).
|
||||||
|
kSNP, //!< CPU has SNP.
|
||||||
kSSE, //!< CPU has SSE.
|
kSSE, //!< CPU has SSE.
|
||||||
kSSE2, //!< CPU has SSE2.
|
kSSE2, //!< CPU has SSE2.
|
||||||
kSSE3, //!< CPU has SSE3.
|
kSSE3, //!< CPU has SSE3.
|
||||||
@@ -136,6 +143,7 @@ public:
|
|||||||
kSVM, //!< CPU has SVM (virtualization) [AMD].
|
kSVM, //!< CPU has SVM (virtualization) [AMD].
|
||||||
kTBM, //!< CPU has TBM (trailing bit manipulation) [AMD].
|
kTBM, //!< CPU has TBM (trailing bit manipulation) [AMD].
|
||||||
kTSX, //!< CPU has TSX.
|
kTSX, //!< CPU has TSX.
|
||||||
|
kTSXLDTRK, //!< CPU has TSXLDTRK.
|
||||||
kVAES, //!< CPU has VAES (vector AES 256|512 bit support).
|
kVAES, //!< CPU has VAES (vector AES 256|512 bit support).
|
||||||
kVMX, //!< CPU has VMX (virtualization) [INTEL].
|
kVMX, //!< CPU has VMX (virtualization) [INTEL].
|
||||||
kVPCLMULQDQ, //!< CPU has VPCLMULQDQ (vector PCLMULQDQ 256|512-bit support).
|
kVPCLMULQDQ, //!< CPU has VPCLMULQDQ (vector PCLMULQDQ 256|512-bit support).
|
||||||
@@ -183,6 +191,9 @@ public:
|
|||||||
ASMJIT_X86_FEATURE(ADX)
|
ASMJIT_X86_FEATURE(ADX)
|
||||||
ASMJIT_X86_FEATURE(AESNI)
|
ASMJIT_X86_FEATURE(AESNI)
|
||||||
ASMJIT_X86_FEATURE(ALTMOVCR8)
|
ASMJIT_X86_FEATURE(ALTMOVCR8)
|
||||||
|
ASMJIT_X86_FEATURE(AMX_BF16)
|
||||||
|
ASMJIT_X86_FEATURE(AMX_INT8)
|
||||||
|
ASMJIT_X86_FEATURE(AMX_TILE)
|
||||||
ASMJIT_X86_FEATURE(AVX)
|
ASMJIT_X86_FEATURE(AVX)
|
||||||
ASMJIT_X86_FEATURE(AVX2)
|
ASMJIT_X86_FEATURE(AVX2)
|
||||||
ASMJIT_X86_FEATURE(AVX512_4FMAPS)
|
ASMJIT_X86_FEATURE(AVX512_4FMAPS)
|
||||||
@@ -229,6 +240,7 @@ public:
|
|||||||
ASMJIT_X86_FEATURE(LAHFSAHF)
|
ASMJIT_X86_FEATURE(LAHFSAHF)
|
||||||
ASMJIT_X86_FEATURE(LWP)
|
ASMJIT_X86_FEATURE(LWP)
|
||||||
ASMJIT_X86_FEATURE(LZCNT)
|
ASMJIT_X86_FEATURE(LZCNT)
|
||||||
|
ASMJIT_X86_FEATURE(MCOMMIT)
|
||||||
ASMJIT_X86_FEATURE(MMX)
|
ASMJIT_X86_FEATURE(MMX)
|
||||||
ASMJIT_X86_FEATURE(MMX2)
|
ASMJIT_X86_FEATURE(MMX2)
|
||||||
ASMJIT_X86_FEATURE(MONITOR)
|
ASMJIT_X86_FEATURE(MONITOR)
|
||||||
@@ -247,16 +259,19 @@ public:
|
|||||||
ASMJIT_X86_FEATURE(PREFETCHW)
|
ASMJIT_X86_FEATURE(PREFETCHW)
|
||||||
ASMJIT_X86_FEATURE(PREFETCHWT1)
|
ASMJIT_X86_FEATURE(PREFETCHWT1)
|
||||||
ASMJIT_X86_FEATURE(RDPID)
|
ASMJIT_X86_FEATURE(RDPID)
|
||||||
|
ASMJIT_X86_FEATURE(RDPRU)
|
||||||
ASMJIT_X86_FEATURE(RDRAND)
|
ASMJIT_X86_FEATURE(RDRAND)
|
||||||
ASMJIT_X86_FEATURE(RDSEED)
|
ASMJIT_X86_FEATURE(RDSEED)
|
||||||
ASMJIT_X86_FEATURE(RDTSC)
|
ASMJIT_X86_FEATURE(RDTSC)
|
||||||
ASMJIT_X86_FEATURE(RDTSCP)
|
ASMJIT_X86_FEATURE(RDTSCP)
|
||||||
ASMJIT_X86_FEATURE(RTM)
|
ASMJIT_X86_FEATURE(RTM)
|
||||||
|
ASMJIT_X86_FEATURE(SERIALIZE)
|
||||||
ASMJIT_X86_FEATURE(SHA)
|
ASMJIT_X86_FEATURE(SHA)
|
||||||
ASMJIT_X86_FEATURE(SKINIT)
|
ASMJIT_X86_FEATURE(SKINIT)
|
||||||
ASMJIT_X86_FEATURE(SMAP)
|
ASMJIT_X86_FEATURE(SMAP)
|
||||||
ASMJIT_X86_FEATURE(SMEP)
|
ASMJIT_X86_FEATURE(SMEP)
|
||||||
ASMJIT_X86_FEATURE(SMX)
|
ASMJIT_X86_FEATURE(SMX)
|
||||||
|
ASMJIT_X86_FEATURE(SNP)
|
||||||
ASMJIT_X86_FEATURE(SSE)
|
ASMJIT_X86_FEATURE(SSE)
|
||||||
ASMJIT_X86_FEATURE(SSE2)
|
ASMJIT_X86_FEATURE(SSE2)
|
||||||
ASMJIT_X86_FEATURE(SSE3)
|
ASMJIT_X86_FEATURE(SSE3)
|
||||||
@@ -267,6 +282,7 @@ public:
|
|||||||
ASMJIT_X86_FEATURE(SVM)
|
ASMJIT_X86_FEATURE(SVM)
|
||||||
ASMJIT_X86_FEATURE(TBM)
|
ASMJIT_X86_FEATURE(TBM)
|
||||||
ASMJIT_X86_FEATURE(TSX)
|
ASMJIT_X86_FEATURE(TSX)
|
||||||
|
ASMJIT_X86_FEATURE(TSXLDTRK)
|
||||||
ASMJIT_X86_FEATURE(XSAVE)
|
ASMJIT_X86_FEATURE(XSAVE)
|
||||||
ASMJIT_X86_FEATURE(XSAVEC)
|
ASMJIT_X86_FEATURE(XSAVEC)
|
||||||
ASMJIT_X86_FEATURE(XSAVEOPT)
|
ASMJIT_X86_FEATURE(XSAVEOPT)
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ struct RegFormatInfo_T {
|
|||||||
X == Reg::kTypeDReg ? 62 :
|
X == Reg::kTypeDReg ? 62 :
|
||||||
X == Reg::kTypeSt ? 47 :
|
X == Reg::kTypeSt ? 47 :
|
||||||
X == Reg::kTypeBnd ? 55 :
|
X == Reg::kTypeBnd ? 55 :
|
||||||
|
X == Reg::kTypeTmm ? 65 :
|
||||||
X == Reg::kTypeRip ? 39 : 0,
|
X == Reg::kTypeRip ? 39 : 0,
|
||||||
|
|
||||||
kFormatIndex = X == Reg::kTypeGpbLo ? 1 :
|
kFormatIndex = X == Reg::kTypeGpbLo ? 1 :
|
||||||
@@ -95,6 +96,7 @@ struct RegFormatInfo_T {
|
|||||||
X == Reg::kTypeDReg ? 80 :
|
X == Reg::kTypeDReg ? 80 :
|
||||||
X == Reg::kTypeSt ? 55 :
|
X == Reg::kTypeSt ? 55 :
|
||||||
X == Reg::kTypeBnd ? 69 :
|
X == Reg::kTypeBnd ? 69 :
|
||||||
|
X == Reg::kTypeTmm ? 89 :
|
||||||
X == Reg::kTypeRip ? 43 : 0,
|
X == Reg::kTypeRip ? 43 : 0,
|
||||||
|
|
||||||
kSpecialIndex = X == Reg::kTypeGpbLo ? 96 :
|
kSpecialIndex = X == Reg::kTypeGpbLo ? 96 :
|
||||||
@@ -146,7 +148,9 @@ static const RegFormatInfo x86RegFormatInfo = {
|
|||||||
"k\0" // #53
|
"k\0" // #53
|
||||||
"bnd\0" // #55
|
"bnd\0" // #55
|
||||||
"cr\0" // #59
|
"cr\0" // #59
|
||||||
"dr\0", // #62
|
"dr\0" // #62
|
||||||
|
"tmm\0" // #65
|
||||||
|
,
|
||||||
|
|
||||||
// Register name entries and strings.
|
// Register name entries and strings.
|
||||||
{ ASMJIT_LOOKUP_TABLE_32(ASMJIT_REG_NAME_ENTRY, 0) },
|
{ ASMJIT_LOOKUP_TABLE_32(ASMJIT_REG_NAME_ENTRY, 0) },
|
||||||
@@ -170,7 +174,8 @@ static const RegFormatInfo x86RegFormatInfo = {
|
|||||||
"dr%u\0" // #80
|
"dr%u\0" // #80
|
||||||
|
|
||||||
"rip\0" // #85
|
"rip\0" // #85
|
||||||
"\0\0\0\0\0\0\0" // #89
|
"tmm%u\0" // #89
|
||||||
|
"\0" // #95
|
||||||
|
|
||||||
"al\0\0" "cl\0\0" "dl\0\0" "bl\0\0" "spl\0" "bpl\0" "sil\0" "dil\0" // #96
|
"al\0\0" "cl\0\0" "dl\0\0" "bl\0\0" "spl\0" "bpl\0" "sil\0" "dil\0" // #96
|
||||||
"ah\0\0" "ch\0\0" "dh\0\0" "bh\0\0" "n/a\0" "n/a\0" "n/a\0" "n/a\0" // #128
|
"ah\0\0" "ch\0\0" "dh\0\0" "bh\0\0" "n/a\0" "n/a\0" "n/a\0" "n/a\0" // #128
|
||||||
@@ -211,6 +216,9 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept
|
|||||||
"ADX\0"
|
"ADX\0"
|
||||||
"AESNI\0"
|
"AESNI\0"
|
||||||
"ALTMOVCR8\0"
|
"ALTMOVCR8\0"
|
||||||
|
"AMX_BF16\0"
|
||||||
|
"AMX_INT8\0"
|
||||||
|
"AMX_TILE\0"
|
||||||
"AVX\0"
|
"AVX\0"
|
||||||
"AVX2\0"
|
"AVX2\0"
|
||||||
"AVX512_4FMAPS\0"
|
"AVX512_4FMAPS\0"
|
||||||
@@ -257,6 +265,7 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept
|
|||||||
"LAHFSAHF\0"
|
"LAHFSAHF\0"
|
||||||
"LWP\0"
|
"LWP\0"
|
||||||
"LZCNT\0"
|
"LZCNT\0"
|
||||||
|
"MCOMMIT\0"
|
||||||
"MMX\0"
|
"MMX\0"
|
||||||
"MMX2\0"
|
"MMX2\0"
|
||||||
"MONITOR\0"
|
"MONITOR\0"
|
||||||
@@ -275,16 +284,19 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept
|
|||||||
"PREFETCHW\0"
|
"PREFETCHW\0"
|
||||||
"PREFETCHWT1\0"
|
"PREFETCHWT1\0"
|
||||||
"RDPID\0"
|
"RDPID\0"
|
||||||
|
"RDPRU\0"
|
||||||
"RDRAND\0"
|
"RDRAND\0"
|
||||||
"RDSEED\0"
|
"RDSEED\0"
|
||||||
"RDTSC\0"
|
"RDTSC\0"
|
||||||
"RDTSCP\0"
|
"RDTSCP\0"
|
||||||
"RTM\0"
|
"RTM\0"
|
||||||
|
"SERIALIZE\0"
|
||||||
"SHA\0"
|
"SHA\0"
|
||||||
"SKINIT\0"
|
"SKINIT\0"
|
||||||
"SMAP\0"
|
"SMAP\0"
|
||||||
"SMEP\0"
|
"SMEP\0"
|
||||||
"SMX\0"
|
"SMX\0"
|
||||||
|
"SNP\0"
|
||||||
"SSE\0"
|
"SSE\0"
|
||||||
"SSE2\0"
|
"SSE2\0"
|
||||||
"SSE3\0"
|
"SSE3\0"
|
||||||
@@ -295,6 +307,7 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept
|
|||||||
"SVM\0"
|
"SVM\0"
|
||||||
"TBM\0"
|
"TBM\0"
|
||||||
"TSX\0"
|
"TSX\0"
|
||||||
|
"TSXLDTRK\0"
|
||||||
"VAES\0"
|
"VAES\0"
|
||||||
"VMX\0"
|
"VMX\0"
|
||||||
"VPCLMULQDQ\0"
|
"VPCLMULQDQ\0"
|
||||||
@@ -308,13 +321,14 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept
|
|||||||
"<Unknown>\0";
|
"<Unknown>\0";
|
||||||
|
|
||||||
static const uint16_t sFeatureIndex[] = {
|
static const uint16_t sFeatureIndex[] = {
|
||||||
0, 5, 8, 11, 17, 24, 28, 34, 44, 48, 53, 67, 81, 93, 107, 117, 128, 138,
|
0, 5, 8, 11, 17, 24, 28, 34, 44, 53, 62, 71, 75, 80, 94, 108, 120, 134, 144,
|
||||||
149, 158, 170, 181, 193, 206, 216, 228, 248, 265, 269, 274, 283, 291, 302,
|
155, 165, 176, 185, 197, 208, 220, 233, 243, 255, 275, 292, 296, 301, 310,
|
||||||
307, 314, 319, 330, 340, 346, 353, 358, 363, 367, 372, 376, 385, 390, 398,
|
318, 329, 334, 341, 346, 357, 367, 373, 380, 385, 390, 394, 399, 403, 412,
|
||||||
404, 409, 413, 418, 427, 431, 437, 441, 446, 454, 463, 469, 479, 487, 491,
|
417, 425, 431, 436, 440, 445, 454, 458, 464, 472, 476, 481, 489, 498, 504,
|
||||||
495, 500, 508, 518, 526, 534, 541, 551, 563, 569, 576, 583, 589, 596, 600,
|
514, 522, 526, 530, 535, 543, 553, 561, 569, 576, 586, 598, 604, 610, 617,
|
||||||
604, 611, 616, 621, 625, 629, 634, 639, 646, 653, 659, 665, 669, 673, 677,
|
624, 630, 637, 641, 651, 655, 662, 667, 672, 676, 680, 684, 689, 694, 701,
|
||||||
682, 686, 697, 705, 714, 718, 724, 731, 740, 747
|
708, 714, 720, 724, 728, 732, 741, 746, 750, 761, 769, 778, 782, 788, 795,
|
||||||
|
804, 811
|
||||||
};
|
};
|
||||||
// @EnumStringEnd@
|
// @EnumStringEnd@
|
||||||
|
|
||||||
|
|||||||
@@ -422,6 +422,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdLddqu, //!< Instruction 'lddqu' {SSE3}.
|
kIdLddqu, //!< Instruction 'lddqu' {SSE3}.
|
||||||
kIdLdmxcsr, //!< Instruction 'ldmxcsr' {SSE}.
|
kIdLdmxcsr, //!< Instruction 'ldmxcsr' {SSE}.
|
||||||
kIdLds, //!< Instruction 'lds' (X86).
|
kIdLds, //!< Instruction 'lds' (X86).
|
||||||
|
kIdLdtilecfg, //!< Instruction 'ldtilecfg' {AMX_TILE} (X64).
|
||||||
kIdLea, //!< Instruction 'lea'.
|
kIdLea, //!< Instruction 'lea'.
|
||||||
kIdLeave, //!< Instruction 'leave'.
|
kIdLeave, //!< Instruction 'leave'.
|
||||||
kIdLes, //!< Instruction 'les' (X86).
|
kIdLes, //!< Instruction 'les' (X86).
|
||||||
@@ -449,6 +450,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdMaxps, //!< Instruction 'maxps' {SSE}.
|
kIdMaxps, //!< Instruction 'maxps' {SSE}.
|
||||||
kIdMaxsd, //!< Instruction 'maxsd' {SSE2}.
|
kIdMaxsd, //!< Instruction 'maxsd' {SSE2}.
|
||||||
kIdMaxss, //!< Instruction 'maxss' {SSE}.
|
kIdMaxss, //!< Instruction 'maxss' {SSE}.
|
||||||
|
kIdMcommit, //!< Instruction 'mcommit' {MCOMMIT}.
|
||||||
kIdMfence, //!< Instruction 'mfence' {SSE2}.
|
kIdMfence, //!< Instruction 'mfence' {SSE2}.
|
||||||
kIdMinpd, //!< Instruction 'minpd' {SSE2}.
|
kIdMinpd, //!< Instruction 'minpd' {SSE2}.
|
||||||
kIdMinps, //!< Instruction 'minps' {SSE}.
|
kIdMinps, //!< Instruction 'minps' {SSE}.
|
||||||
@@ -550,6 +552,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdPcmpistri, //!< Instruction 'pcmpistri' {SSE4_2}.
|
kIdPcmpistri, //!< Instruction 'pcmpistri' {SSE4_2}.
|
||||||
kIdPcmpistrm, //!< Instruction 'pcmpistrm' {SSE4_2}.
|
kIdPcmpistrm, //!< Instruction 'pcmpistrm' {SSE4_2}.
|
||||||
kIdPcommit, //!< Instruction 'pcommit' {PCOMMIT}.
|
kIdPcommit, //!< Instruction 'pcommit' {PCOMMIT}.
|
||||||
|
kIdPconfig, //!< Instruction 'pconfig' {PCONFIG}.
|
||||||
kIdPdep, //!< Instruction 'pdep' {BMI2}.
|
kIdPdep, //!< Instruction 'pdep' {BMI2}.
|
||||||
kIdPext, //!< Instruction 'pext' {BMI2}.
|
kIdPext, //!< Instruction 'pext' {BMI2}.
|
||||||
kIdPextrb, //!< Instruction 'pextrb' {SSE4_1}.
|
kIdPextrb, //!< Instruction 'pextrb' {SSE4_1}.
|
||||||
@@ -653,6 +656,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdPslldq, //!< Instruction 'pslldq' {SSE2}.
|
kIdPslldq, //!< Instruction 'pslldq' {SSE2}.
|
||||||
kIdPsllq, //!< Instruction 'psllq' {MMX|SSE2}.
|
kIdPsllq, //!< Instruction 'psllq' {MMX|SSE2}.
|
||||||
kIdPsllw, //!< Instruction 'psllw' {MMX|SSE2}.
|
kIdPsllw, //!< Instruction 'psllw' {MMX|SSE2}.
|
||||||
|
kIdPsmash, //!< Instruction 'psmash' {SNP} (X64).
|
||||||
kIdPsrad, //!< Instruction 'psrad' {MMX|SSE2}.
|
kIdPsrad, //!< Instruction 'psrad' {MMX|SSE2}.
|
||||||
kIdPsraw, //!< Instruction 'psraw' {MMX|SSE2}.
|
kIdPsraw, //!< Instruction 'psraw' {MMX|SSE2}.
|
||||||
kIdPsrld, //!< Instruction 'psrld' {MMX|SSE2}.
|
kIdPsrld, //!< Instruction 'psrld' {MMX|SSE2}.
|
||||||
@@ -683,6 +687,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdPushf, //!< Instruction 'pushf'.
|
kIdPushf, //!< Instruction 'pushf'.
|
||||||
kIdPushfd, //!< Instruction 'pushfd' (X86).
|
kIdPushfd, //!< Instruction 'pushfd' (X86).
|
||||||
kIdPushfq, //!< Instruction 'pushfq' (X64).
|
kIdPushfq, //!< Instruction 'pushfq' (X64).
|
||||||
|
kIdPvalidate, //!< Instruction 'pvalidate' {SNP}.
|
||||||
kIdPxor, //!< Instruction 'pxor' {MMX|SSE2}.
|
kIdPxor, //!< Instruction 'pxor' {MMX|SSE2}.
|
||||||
kIdRcl, //!< Instruction 'rcl'.
|
kIdRcl, //!< Instruction 'rcl'.
|
||||||
kIdRcpps, //!< Instruction 'rcpps' {SSE}.
|
kIdRcpps, //!< Instruction 'rcpps' {SSE}.
|
||||||
@@ -693,11 +698,14 @@ struct Inst : public BaseInst {
|
|||||||
kIdRdmsr, //!< Instruction 'rdmsr' {MSR}.
|
kIdRdmsr, //!< Instruction 'rdmsr' {MSR}.
|
||||||
kIdRdpid, //!< Instruction 'rdpid' {RDPID}.
|
kIdRdpid, //!< Instruction 'rdpid' {RDPID}.
|
||||||
kIdRdpmc, //!< Instruction 'rdpmc'.
|
kIdRdpmc, //!< Instruction 'rdpmc'.
|
||||||
|
kIdRdpru, //!< Instruction 'rdpru' {RDPRU}.
|
||||||
kIdRdrand, //!< Instruction 'rdrand' {RDRAND}.
|
kIdRdrand, //!< Instruction 'rdrand' {RDRAND}.
|
||||||
kIdRdseed, //!< Instruction 'rdseed' {RDSEED}.
|
kIdRdseed, //!< Instruction 'rdseed' {RDSEED}.
|
||||||
kIdRdtsc, //!< Instruction 'rdtsc' {RDTSC}.
|
kIdRdtsc, //!< Instruction 'rdtsc' {RDTSC}.
|
||||||
kIdRdtscp, //!< Instruction 'rdtscp' {RDTSCP}.
|
kIdRdtscp, //!< Instruction 'rdtscp' {RDTSCP}.
|
||||||
kIdRet, //!< Instruction 'ret'.
|
kIdRet, //!< Instruction 'ret'.
|
||||||
|
kIdRmpadjust, //!< Instruction 'rmpadjust' {SNP} (X64).
|
||||||
|
kIdRmpupdate, //!< Instruction 'rmpupdate' {SNP} (X64).
|
||||||
kIdRol, //!< Instruction 'rol'.
|
kIdRol, //!< Instruction 'rol'.
|
||||||
kIdRor, //!< Instruction 'ror'.
|
kIdRor, //!< Instruction 'ror'.
|
||||||
kIdRorx, //!< Instruction 'rorx' {BMI2}.
|
kIdRorx, //!< Instruction 'rorx' {BMI2}.
|
||||||
@@ -714,6 +722,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdSarx, //!< Instruction 'sarx' {BMI2}.
|
kIdSarx, //!< Instruction 'sarx' {BMI2}.
|
||||||
kIdSbb, //!< Instruction 'sbb'.
|
kIdSbb, //!< Instruction 'sbb'.
|
||||||
kIdScas, //!< Instruction 'scas'.
|
kIdScas, //!< Instruction 'scas'.
|
||||||
|
kIdSerialize, //!< Instruction 'serialize' {SERIALIZE}.
|
||||||
kIdSeta, //!< Instruction 'seta'.
|
kIdSeta, //!< Instruction 'seta'.
|
||||||
kIdSetae, //!< Instruction 'setae'.
|
kIdSetae, //!< Instruction 'setae'.
|
||||||
kIdSetb, //!< Instruction 'setb'.
|
kIdSetb, //!< Instruction 'setb'.
|
||||||
@@ -778,6 +787,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdStmxcsr, //!< Instruction 'stmxcsr' {SSE}.
|
kIdStmxcsr, //!< Instruction 'stmxcsr' {SSE}.
|
||||||
kIdStos, //!< Instruction 'stos'.
|
kIdStos, //!< Instruction 'stos'.
|
||||||
kIdStr, //!< Instruction 'str'.
|
kIdStr, //!< Instruction 'str'.
|
||||||
|
kIdSttilecfg, //!< Instruction 'sttilecfg' {AMX_TILE} (X64).
|
||||||
kIdSub, //!< Instruction 'sub'.
|
kIdSub, //!< Instruction 'sub'.
|
||||||
kIdSubpd, //!< Instruction 'subpd' {SSE2}.
|
kIdSubpd, //!< Instruction 'subpd' {SSE2}.
|
||||||
kIdSubps, //!< Instruction 'subps' {SSE}.
|
kIdSubps, //!< Instruction 'subps' {SSE}.
|
||||||
@@ -791,12 +801,25 @@ struct Inst : public BaseInst {
|
|||||||
kIdSysret, //!< Instruction 'sysret' (X64).
|
kIdSysret, //!< Instruction 'sysret' (X64).
|
||||||
kIdSysret64, //!< Instruction 'sysret64' (X64).
|
kIdSysret64, //!< Instruction 'sysret64' (X64).
|
||||||
kIdT1mskc, //!< Instruction 't1mskc' {TBM}.
|
kIdT1mskc, //!< Instruction 't1mskc' {TBM}.
|
||||||
|
kIdTdpbf16ps, //!< Instruction 'tdpbf16ps' {AMX_BF16} (X64).
|
||||||
|
kIdTdpbssd, //!< Instruction 'tdpbssd' {AMX_INT8} (X64).
|
||||||
|
kIdTdpbsud, //!< Instruction 'tdpbsud' {AMX_INT8} (X64).
|
||||||
|
kIdTdpbusd, //!< Instruction 'tdpbusd' {AMX_INT8} (X64).
|
||||||
|
kIdTdpbuud, //!< Instruction 'tdpbuud' {AMX_INT8} (X64).
|
||||||
kIdTest, //!< Instruction 'test'.
|
kIdTest, //!< Instruction 'test'.
|
||||||
|
kIdTileloadd, //!< Instruction 'tileloadd' {AMX_TILE} (X64).
|
||||||
|
kIdTileloaddt1, //!< Instruction 'tileloaddt1' {AMX_TILE} (X64).
|
||||||
|
kIdTilerelease, //!< Instruction 'tilerelease' {AMX_TILE} (X64).
|
||||||
|
kIdTilestored, //!< Instruction 'tilestored' {AMX_TILE} (X64).
|
||||||
|
kIdTilezero, //!< Instruction 'tilezero' {AMX_TILE} (X64).
|
||||||
|
kIdTpause, //!< Instruction 'tpause' {WAITPKG}.
|
||||||
kIdTzcnt, //!< Instruction 'tzcnt' {BMI}.
|
kIdTzcnt, //!< Instruction 'tzcnt' {BMI}.
|
||||||
kIdTzmsk, //!< Instruction 'tzmsk' {TBM}.
|
kIdTzmsk, //!< Instruction 'tzmsk' {TBM}.
|
||||||
kIdUcomisd, //!< Instruction 'ucomisd' {SSE2}.
|
kIdUcomisd, //!< Instruction 'ucomisd' {SSE2}.
|
||||||
kIdUcomiss, //!< Instruction 'ucomiss' {SSE}.
|
kIdUcomiss, //!< Instruction 'ucomiss' {SSE}.
|
||||||
kIdUd2, //!< Instruction 'ud2'.
|
kIdUd2, //!< Instruction 'ud2'.
|
||||||
|
kIdUmonitor, //!< Instruction 'umonitor' {WAITPKG}.
|
||||||
|
kIdUmwait, //!< Instruction 'umwait' {WAITPKG}.
|
||||||
kIdUnpckhpd, //!< Instruction 'unpckhpd' {SSE2}.
|
kIdUnpckhpd, //!< Instruction 'unpckhpd' {SSE2}.
|
||||||
kIdUnpckhps, //!< Instruction 'unpckhps' {SSE}.
|
kIdUnpckhps, //!< Instruction 'unpckhps' {SSE}.
|
||||||
kIdUnpcklpd, //!< Instruction 'unpcklpd' {SSE2}.
|
kIdUnpcklpd, //!< Instruction 'unpcklpd' {SSE2}.
|
||||||
@@ -1119,6 +1142,8 @@ struct Inst : public BaseInst {
|
|||||||
kIdVmxon, //!< Instruction 'vmxon' {VMX}.
|
kIdVmxon, //!< Instruction 'vmxon' {VMX}.
|
||||||
kIdVorpd, //!< Instruction 'vorpd' {AVX|AVX512_DQ+VL}.
|
kIdVorpd, //!< Instruction 'vorpd' {AVX|AVX512_DQ+VL}.
|
||||||
kIdVorps, //!< Instruction 'vorps' {AVX|AVX512_DQ+VL}.
|
kIdVorps, //!< Instruction 'vorps' {AVX|AVX512_DQ+VL}.
|
||||||
|
kIdVp2intersectd, //!< Instruction 'vp2intersectd' {AVX512_VP2INTERSECT}.
|
||||||
|
kIdVp2intersectq, //!< Instruction 'vp2intersectq' {AVX512_VP2INTERSECT}.
|
||||||
kIdVp4dpwssd, //!< Instruction 'vp4dpwssd' {AVX512_4VNNIW}.
|
kIdVp4dpwssd, //!< Instruction 'vp4dpwssd' {AVX512_4VNNIW}.
|
||||||
kIdVp4dpwssds, //!< Instruction 'vp4dpwssds' {AVX512_4VNNIW}.
|
kIdVp4dpwssds, //!< Instruction 'vp4dpwssds' {AVX512_4VNNIW}.
|
||||||
kIdVpabsb, //!< Instruction 'vpabsb' {AVX|AVX2|AVX512_BW+VL}.
|
kIdVpabsb, //!< Instruction 'vpabsb' {AVX|AVX2|AVX512_BW+VL}.
|
||||||
@@ -1538,6 +1563,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdXor, //!< Instruction 'xor'.
|
kIdXor, //!< Instruction 'xor'.
|
||||||
kIdXorpd, //!< Instruction 'xorpd' {SSE2}.
|
kIdXorpd, //!< Instruction 'xorpd' {SSE2}.
|
||||||
kIdXorps, //!< Instruction 'xorps' {SSE}.
|
kIdXorps, //!< Instruction 'xorps' {SSE}.
|
||||||
|
kIdXresldtrk, //!< Instruction 'xresldtrk' {TSXLDTRK}.
|
||||||
kIdXrstor, //!< Instruction 'xrstor' {XSAVE}.
|
kIdXrstor, //!< Instruction 'xrstor' {XSAVE}.
|
||||||
kIdXrstor64, //!< Instruction 'xrstor64' {XSAVE} (X64).
|
kIdXrstor64, //!< Instruction 'xrstor64' {XSAVE} (X64).
|
||||||
kIdXrstors, //!< Instruction 'xrstors' {XSAVES}.
|
kIdXrstors, //!< Instruction 'xrstors' {XSAVES}.
|
||||||
@@ -1551,6 +1577,7 @@ struct Inst : public BaseInst {
|
|||||||
kIdXsaves, //!< Instruction 'xsaves' {XSAVES}.
|
kIdXsaves, //!< Instruction 'xsaves' {XSAVES}.
|
||||||
kIdXsaves64, //!< Instruction 'xsaves64' {XSAVES} (X64).
|
kIdXsaves64, //!< Instruction 'xsaves64' {XSAVES} (X64).
|
||||||
kIdXsetbv, //!< Instruction 'xsetbv' {XSAVE}.
|
kIdXsetbv, //!< Instruction 'xsetbv' {XSAVE}.
|
||||||
|
kIdXsusldtrk, //!< Instruction 'xsusldtrk' {TSXLDTRK}.
|
||||||
kIdXtest, //!< Instruction 'xtest' {TSX}.
|
kIdXtest, //!< Instruction 'xtest' {TSX}.
|
||||||
_kIdCount
|
_kIdCount
|
||||||
// ${InstId:End}
|
// ${InstId:End}
|
||||||
|
|||||||
@@ -142,6 +142,7 @@ struct X86ValidationData {
|
|||||||
(X == Reg::kTypeDReg ) ? InstDB::kOpDReg : \
|
(X == Reg::kTypeDReg ) ? InstDB::kOpDReg : \
|
||||||
(X == Reg::kTypeSt ) ? InstDB::kOpSt : \
|
(X == Reg::kTypeSt ) ? InstDB::kOpSt : \
|
||||||
(X == Reg::kTypeBnd ) ? InstDB::kOpBnd : \
|
(X == Reg::kTypeBnd ) ? InstDB::kOpBnd : \
|
||||||
|
(X == Reg::kTypeTmm ) ? InstDB::kOpTmm : \
|
||||||
(X == Reg::kTypeRip ) ? InstDB::kOpNone : InstDB::kOpNone
|
(X == Reg::kTypeRip ) ? InstDB::kOpNone : InstDB::kOpNone
|
||||||
static const uint32_t _x86OpFlagFromRegType[Reg::kTypeMax + 1] = { ASMJIT_LOOKUP_TABLE_32(VALUE, 0) };
|
static const uint32_t _x86OpFlagFromRegType[Reg::kTypeMax + 1] = { ASMJIT_LOOKUP_TABLE_32(VALUE, 0) };
|
||||||
#undef VALUE
|
#undef VALUE
|
||||||
@@ -162,6 +163,7 @@ static const uint32_t _x86OpFlagFromRegType[Reg::kTypeMax + 1] = { ASMJIT_LOOKUP
|
|||||||
(X == Reg::kTypeDReg ) ? 0x000000FFu : \
|
(X == Reg::kTypeDReg ) ? 0x000000FFu : \
|
||||||
(X == Reg::kTypeSt ) ? 0x000000FFu : \
|
(X == Reg::kTypeSt ) ? 0x000000FFu : \
|
||||||
(X == Reg::kTypeBnd ) ? 0x0000000Fu : \
|
(X == Reg::kTypeBnd ) ? 0x0000000Fu : \
|
||||||
|
(X == Reg::kTypeTmm ) ? 0x000000FFu : \
|
||||||
(X == Reg::kTypeRip ) ? 0x00000001u : 0u
|
(X == Reg::kTypeRip ) ? 0x00000001u : 0u
|
||||||
|
|
||||||
#define REG_MASK_FROM_REG_TYPE_X64(X) \
|
#define REG_MASK_FROM_REG_TYPE_X64(X) \
|
||||||
@@ -180,6 +182,7 @@ static const uint32_t _x86OpFlagFromRegType[Reg::kTypeMax + 1] = { ASMJIT_LOOKUP
|
|||||||
(X == Reg::kTypeDReg ) ? 0x0000FFFFu : \
|
(X == Reg::kTypeDReg ) ? 0x0000FFFFu : \
|
||||||
(X == Reg::kTypeSt ) ? 0x000000FFu : \
|
(X == Reg::kTypeSt ) ? 0x000000FFu : \
|
||||||
(X == Reg::kTypeBnd ) ? 0x0000000Fu : \
|
(X == Reg::kTypeBnd ) ? 0x0000000Fu : \
|
||||||
|
(X == Reg::kTypeTmm ) ? 0x000000FFu : \
|
||||||
(X == Reg::kTypeRip ) ? 0x00000001u : 0u
|
(X == Reg::kTypeRip ) ? 0x00000001u : 0u
|
||||||
|
|
||||||
static const X86ValidationData _x86ValidationData = {
|
static const X86ValidationData _x86ValidationData = {
|
||||||
@@ -821,13 +824,15 @@ Error InstInternal::queryRWInfo(uint32_t arch, const BaseInst& inst, const Opera
|
|||||||
const InstDB::CommonInfoTableB& tabB = InstDB::_commonInfoTableB[InstDB::_instInfoTable[instId]._commonInfoIndexB];
|
const InstDB::CommonInfoTableB& tabB = InstDB::_commonInfoTableB[InstDB::_instInfoTable[instId]._commonInfoIndexB];
|
||||||
const InstDB::RWFlagsInfoTable& rwFlags = InstDB::_rwFlagsInfoTable[tabB._rwFlagsIndex];
|
const InstDB::RWFlagsInfoTable& rwFlags = InstDB::_rwFlagsInfoTable[tabB._rwFlagsIndex];
|
||||||
|
|
||||||
// Each RWInfo contains two indexes
|
|
||||||
// [0] - OpCount == 2
|
// There are two data tables, one for `opCount == 2` and the second for
|
||||||
// [1] - OpCount != 2
|
// `opCount != 2`. There are two reasons for that:
|
||||||
// They are used this way as there are instructions that have 2 and 3
|
// - There are instructions that share the same name that have both 2
|
||||||
// operand overloads that use different semantics. So instead of adding
|
// or 3 operands, which have different RW information / semantics.
|
||||||
// more special cases we just separated their data tables.
|
// - There must be 2 tables otherwise the lookup index won't fit into
|
||||||
const InstDB::RWInfo& instRwInfo = InstDB::rwInfo[InstDB::rwInfoIndex[instId * 2u + uint32_t(opCount != 2)]];
|
// 8 bits (there is more than 256 records of combined rwInfo A and B).
|
||||||
|
const InstDB::RWInfo& instRwInfo = opCount == 2 ? InstDB::rwInfoA[InstDB::rwInfoIndexA[instId]]
|
||||||
|
: InstDB::rwInfoB[InstDB::rwInfoIndexB[instId]];
|
||||||
const InstDB::RWInfoRm& instRmInfo = InstDB::rwInfoRm[instRwInfo.rmInfo];
|
const InstDB::RWInfoRm& instRmInfo = InstDB::rwInfoRm[instRwInfo.rmInfo];
|
||||||
|
|
||||||
out->_instFlags = 0;
|
out->_instFlags = 0;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -74,17 +74,18 @@ enum OpFlags : uint32_t {
|
|||||||
kOpDReg = 0x00001000u, //!< Operand can be DReg (debug register).
|
kOpDReg = 0x00001000u, //!< Operand can be DReg (debug register).
|
||||||
kOpSt = 0x00002000u, //!< Operand can be 80-bit ST register (X87).
|
kOpSt = 0x00002000u, //!< Operand can be 80-bit ST register (X87).
|
||||||
kOpBnd = 0x00004000u, //!< Operand can be 128-bit BND register.
|
kOpBnd = 0x00004000u, //!< Operand can be 128-bit BND register.
|
||||||
kOpAllRegs = 0x00007FFFu, //!< Combination of all possible registers.
|
kOpTmm = 0x00008000u, //!< Operand can be 0..8192-bit TMM register.
|
||||||
|
kOpAllRegs = 0x0000FFFFu, //!< Combination of all possible registers.
|
||||||
|
|
||||||
kOpI4 = 0x00010000u, //!< Operand can be unsigned 4-bit immediate.
|
kOpI4 = 0x00010000u, //!< Operand can be unsigned 4-bit immediate.
|
||||||
kOpU4 = 0x00020000u, //!< Operand can be unsigned 4-bit immediate.
|
kOpU4 = 0x00020000u, //!< Operand can be unsigned 4-bit immediate.
|
||||||
kOpI8 = 0x00040000u, //!< Operand can be signed 8-bit immediate.
|
kOpI8 = 0x00040000u, //!< Operand can be signed 8-bit immediate.
|
||||||
kOpU8 = 0x00080000u, //!< Operand can be unsigned 8-bit immediate.
|
kOpU8 = 0x00080000u, //!< Operand can be unsigned 8-bit immediate.
|
||||||
kOpI16 = 0x00100000u, //!< Operand can be signed 16-bit immediate.
|
kOpI16 = 0x00100000u, //!< Operand can be signed 16-bit immediate.
|
||||||
kOpU16 = 0x00200000u, //!< Operand can be unsigned 16-bit immediate.
|
kOpU16 = 0x00200000u, //!< Operand can be unsigned 16-bit immediate.
|
||||||
kOpI32 = 0x00400000u, //!< Operand can be signed 32-bit immediate.
|
kOpI32 = 0x00400000u, //!< Operand can be signed 32-bit immediate.
|
||||||
kOpU32 = 0x00800000u, //!< Operand can be unsigned 32-bit immediate.
|
kOpU32 = 0x00800000u, //!< Operand can be unsigned 32-bit immediate.
|
||||||
kOpI64 = 0x01000000u, //!< Operand can be signed 64-bit immediate.
|
kOpI64 = 0x01000000u, //!< Operand can be signed 64-bit immediate.
|
||||||
kOpU64 = 0x02000000u, //!< Operand can be unsigned 64-bit immediate.
|
kOpU64 = 0x02000000u, //!< Operand can be unsigned 64-bit immediate.
|
||||||
kOpAllImm = 0x03FF0000u, //!< Operand can be any immediate.
|
kOpAllImm = 0x03FF0000u, //!< Operand can be any immediate.
|
||||||
|
|
||||||
@@ -129,7 +130,8 @@ enum MemFlags : uint32_t {
|
|||||||
kMemOpDs = 0x1000u, //!< Implicit memory operand's DS segment.
|
kMemOpDs = 0x1000u, //!< Implicit memory operand's DS segment.
|
||||||
kMemOpEs = 0x2000u, //!< Implicit memory operand's ES segment.
|
kMemOpEs = 0x2000u, //!< Implicit memory operand's ES segment.
|
||||||
|
|
||||||
kMemOpMib = 0x4000u //!< Operand must be MIB (base+index) pointer.
|
kMemOpMib = 0x4000u, //!< Operand must be MIB (base+index) pointer.
|
||||||
|
kMemOpTMem = 0x8000u //!< Operand is a sib_mem (ADX memory operand).
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -156,6 +158,7 @@ enum Flags : uint32_t {
|
|||||||
//
|
//
|
||||||
// These describe optional X86 prefixes that can be used to change the instruction's operation.
|
// These describe optional X86 prefixes that can be used to change the instruction's operation.
|
||||||
|
|
||||||
|
kFlagTsib = 0x00000800u, //!< Instruction uses TSIB (or SIB_MEM) encoding (MODRM followed by SIB).
|
||||||
kFlagRep = 0x00001000u, //!< Instruction can be prefixed with using the REP(REPE) or REPNE prefix.
|
kFlagRep = 0x00001000u, //!< Instruction can be prefixed with using the REP(REPE) or REPNE prefix.
|
||||||
kFlagRepIgnored = 0x00002000u, //!< Instruction ignores REP|REPNE prefixes, but they are accepted.
|
kFlagRepIgnored = 0x00002000u, //!< Instruction ignores REP|REPNE prefixes, but they are accepted.
|
||||||
kFlagLock = 0x00004000u, //!< Instruction can be prefixed with using the LOCK prefix.
|
kFlagLock = 0x00004000u, //!< Instruction can be prefixed with using the LOCK prefix.
|
||||||
@@ -319,6 +322,8 @@ struct CommonInfo {
|
|||||||
inline bool isMibOp() const noexcept { return hasFlag(kFlagMib); }
|
inline bool isMibOp() const noexcept { return hasFlag(kFlagMib); }
|
||||||
//! Tests whether the instruction uses VSIB.
|
//! Tests whether the instruction uses VSIB.
|
||||||
inline bool isVsibOp() const noexcept { return hasFlag(kFlagVsib); }
|
inline bool isVsibOp() const noexcept { return hasFlag(kFlagVsib); }
|
||||||
|
//! Tests whether the instruction uses TSIB (AMX, instruction requires MOD+SIB).
|
||||||
|
inline bool isTsibOp() const noexcept { return hasFlag(kFlagTsib); }
|
||||||
//! Tests whether the instruction uses VEX (can be set together with EVEX if both are encodable).
|
//! Tests whether the instruction uses VEX (can be set together with EVEX if both are encodable).
|
||||||
inline bool isVex() const noexcept { return hasFlag(kFlagVex); }
|
inline bool isVex() const noexcept { return hasFlag(kFlagVex); }
|
||||||
//! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable).
|
//! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable).
|
||||||
|
|||||||
@@ -62,6 +62,8 @@ enum EncodingId : uint32_t {
|
|||||||
kEncodingX86M_Only, //!< X86 [M] (restricted to memory operand of any size).
|
kEncodingX86M_Only, //!< X86 [M] (restricted to memory operand of any size).
|
||||||
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.
|
||||||
|
kEncodingX86R32_EDX_EAX, //!< X86 [R32] followed by implicit EDX and EAX.
|
||||||
kEncodingX86Rm, //!< X86 [RM] (doesn't handle single-byte size).
|
kEncodingX86Rm, //!< X86 [RM] (doesn't handle single-byte size).
|
||||||
kEncodingX86Rm_Raw66H, //!< X86 [RM] (used by LZCNT, POPCNT, and TZCNT).
|
kEncodingX86Rm_Raw66H, //!< X86 [RM] (used by LZCNT, POPCNT, and TZCNT).
|
||||||
kEncodingX86Rm_NoSize, //!< X86 [RM] (doesn't add REX.W prefix if 64-bit reg is used).
|
kEncodingX86Rm_NoSize, //!< X86 [RM] (doesn't add REX.W prefix if 64-bit reg is used).
|
||||||
@@ -132,6 +134,7 @@ enum EncodingId : uint32_t {
|
|||||||
kEncodingExtInsertq, //!< EXT insrq (SSE4A).
|
kEncodingExtInsertq, //!< EXT insrq (SSE4A).
|
||||||
kEncodingExt3dNow, //!< EXT [RMI] (3DNOW specific).
|
kEncodingExt3dNow, //!< EXT [RMI] (3DNOW specific).
|
||||||
kEncodingVexOp, //!< VEX [OP].
|
kEncodingVexOp, //!< VEX [OP].
|
||||||
|
kEncodingVexOpMod, //!< VEX [OP] with MODR/M.
|
||||||
kEncodingVexKmov, //!< VEX [RM|MR] (used by kmov[b|w|d|q]).
|
kEncodingVexKmov, //!< VEX [RM|MR] (used by kmov[b|w|d|q]).
|
||||||
kEncodingVexR_Wx, //!< VEX|EVEX [R] (propagatex VEX.W if GPQ used).
|
kEncodingVexR_Wx, //!< VEX|EVEX [R] (propagatex VEX.W if GPQ used).
|
||||||
kEncodingVexM, //!< VEX|EVEX [M].
|
kEncodingVexM, //!< VEX|EVEX [M].
|
||||||
@@ -154,6 +157,7 @@ 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_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].
|
||||||
@@ -187,6 +191,11 @@ enum EncodingId : uint32_t {
|
|||||||
kEncodingVexMovssMovsd, //!< VEX|EVEX vmovss, vmovsd.
|
kEncodingVexMovssMovsd, //!< VEX|EVEX vmovss, vmovsd.
|
||||||
kEncodingFma4, //!< FMA4 [R, R, R/M, R/M].
|
kEncodingFma4, //!< FMA4 [R, R, R/M, R/M].
|
||||||
kEncodingFma4_Lx, //!< FMA4 [R, R, R/M, R/M] (propagates AVX.L if YMM used).
|
kEncodingFma4_Lx, //!< FMA4 [R, R, R/M, R/M] (propagates AVX.L if YMM used).
|
||||||
|
kEncodingAmxCfg, //!< AMX ldtilecfg/sttilecfg.
|
||||||
|
kEncodingAmxR, //!< AMX [R] - tilezero.
|
||||||
|
kEncodingAmxRm, //!< AMX tileloadd/tileloaddt1.
|
||||||
|
kEncodingAmxMr, //!< AMX tilestored.
|
||||||
|
kEncodingAmxRmv, //!< AMX instructions that use TMM registers.
|
||||||
kEncodingCount //!< Count of instruction encodings.
|
kEncodingCount //!< Count of instruction encodings.
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -288,8 +297,10 @@ struct RWFlagsInfoTable {
|
|||||||
uint32_t writeFlags;
|
uint32_t writeFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const uint8_t rwInfoIndex[Inst::_kIdCount * 2];
|
extern const uint8_t rwInfoIndexA[Inst::_kIdCount];
|
||||||
extern const RWInfo rwInfo[];
|
extern const uint8_t rwInfoIndexB[Inst::_kIdCount];
|
||||||
|
extern const RWInfo rwInfoA[];
|
||||||
|
extern const RWInfo rwInfoB[];
|
||||||
extern const RWInfoOp rwInfoOp[];
|
extern const RWInfoOp rwInfoOp[];
|
||||||
extern const RWInfoRm rwInfoRm[];
|
extern const RWInfoRm rwInfoRm[];
|
||||||
extern const RWFlagsInfoTable _rwFlagsInfoTable[];
|
extern const RWFlagsInfoTable _rwFlagsInfoTable[];
|
||||||
|
|||||||
@@ -337,14 +337,17 @@ struct Opcode {
|
|||||||
k000F3A = kPP_00 | kMM_0F3A, // '0F3A'
|
k000F3A = kPP_00 | kMM_0F3A, // '0F3A'
|
||||||
k660000 = kPP_66 | kMM_00, // '66'
|
k660000 = kPP_66 | kMM_00, // '66'
|
||||||
k660F00 = kPP_66 | kMM_0F, // '660F'
|
k660F00 = kPP_66 | kMM_0F, // '660F'
|
||||||
|
k660F01 = kPP_66 | kMM_0F01, // '660F01'
|
||||||
k660F38 = kPP_66 | kMM_0F38, // '660F38'
|
k660F38 = kPP_66 | kMM_0F38, // '660F38'
|
||||||
k660F3A = kPP_66 | kMM_0F3A, // '660F3A'
|
k660F3A = kPP_66 | kMM_0F3A, // '660F3A'
|
||||||
kF20000 = kPP_F2 | kMM_00, // 'F2'
|
kF20000 = kPP_F2 | kMM_00, // 'F2'
|
||||||
kF20F00 = kPP_F2 | kMM_0F, // 'F20F'
|
kF20F00 = kPP_F2 | kMM_0F, // 'F20F'
|
||||||
|
kF20F01 = kPP_F2 | kMM_0F01, // 'F20F01'
|
||||||
kF20F38 = kPP_F2 | kMM_0F38, // 'F20F38'
|
kF20F38 = kPP_F2 | kMM_0F38, // 'F20F38'
|
||||||
kF20F3A = kPP_F2 | kMM_0F3A, // 'F20F3A'
|
kF20F3A = kPP_F2 | kMM_0F3A, // 'F20F3A'
|
||||||
kF30000 = kPP_F3 | kMM_00, // 'F3'
|
kF30000 = kPP_F3 | kMM_00, // 'F3'
|
||||||
kF30F00 = kPP_F3 | kMM_0F, // 'F30F'
|
kF30F00 = kPP_F3 | kMM_0F, // 'F30F'
|
||||||
|
kF30F01 = kPP_F3 | kMM_0F01, // 'F30F01'
|
||||||
kF30F38 = kPP_F3 | kMM_0F38, // 'F30F38'
|
kF30F38 = kPP_F3 | kMM_0F38, // 'F30F38'
|
||||||
kF30F3A = kPP_F3 | kMM_0F3A, // 'F30F3A'
|
kF30F3A = kPP_F3 | kMM_0F3A, // 'F30F3A'
|
||||||
kFPU_00 = kPP_00 | kMM_00, // '__' (FPU)
|
kFPU_00 = kPP_00 | kMM_00, // '__' (FPU)
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ class CReg;
|
|||||||
class DReg;
|
class DReg;
|
||||||
class St;
|
class St;
|
||||||
class Bnd;
|
class Bnd;
|
||||||
|
class Tmm;
|
||||||
class Rip;
|
class Rip;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -142,7 +143,8 @@ ASMJIT_DEFINE_REG_TRAITS(CReg , BaseReg::kTypeCustom + 1, BaseReg::kGroupVirt +
|
|||||||
ASMJIT_DEFINE_REG_TRAITS(DReg , BaseReg::kTypeCustom + 2, BaseReg::kGroupVirt + 2, 0 , 16, Type::kIdVoid );
|
ASMJIT_DEFINE_REG_TRAITS(DReg , BaseReg::kTypeCustom + 2, BaseReg::kGroupVirt + 2, 0 , 16, Type::kIdVoid );
|
||||||
ASMJIT_DEFINE_REG_TRAITS(St , BaseReg::kTypeCustom + 3, BaseReg::kGroupVirt + 3, 10, 8 , Type::kIdF80 );
|
ASMJIT_DEFINE_REG_TRAITS(St , BaseReg::kTypeCustom + 3, BaseReg::kGroupVirt + 3, 10, 8 , Type::kIdF80 );
|
||||||
ASMJIT_DEFINE_REG_TRAITS(Bnd , BaseReg::kTypeCustom + 4, BaseReg::kGroupVirt + 4, 16, 4 , Type::kIdVoid );
|
ASMJIT_DEFINE_REG_TRAITS(Bnd , BaseReg::kTypeCustom + 4, BaseReg::kGroupVirt + 4, 16, 4 , Type::kIdVoid );
|
||||||
ASMJIT_DEFINE_REG_TRAITS(Rip , BaseReg::kTypeIP , BaseReg::kGroupVirt + 5, 0 , 1 , Type::kIdVoid );
|
ASMJIT_DEFINE_REG_TRAITS(Tmm , BaseReg::kTypeCustom + 5, BaseReg::kGroupVirt + 5, 0 , 8 , Type::kIdVoid );
|
||||||
|
ASMJIT_DEFINE_REG_TRAITS(Rip , BaseReg::kTypeIP , BaseReg::kGroupVirt + 6, 0 , 1 , Type::kIdVoid );
|
||||||
//! \endcond
|
//! \endcond
|
||||||
|
|
||||||
//! Register (X86).
|
//! Register (X86).
|
||||||
@@ -152,41 +154,78 @@ public:
|
|||||||
|
|
||||||
//! Register type.
|
//! Register type.
|
||||||
enum RegType : uint32_t {
|
enum RegType : uint32_t {
|
||||||
kTypeNone = BaseReg::kTypeNone, //!< No register type or invalid register.
|
//! No register type or invalid register.
|
||||||
kTypeGpbLo = BaseReg::kTypeGp8Lo, //!< Low GPB register (AL, BL, CL, DL, ...).
|
kTypeNone = BaseReg::kTypeNone,
|
||||||
kTypeGpbHi = BaseReg::kTypeGp8Hi, //!< High GPB register (AH, BH, CH, DH only).
|
|
||||||
kTypeGpw = BaseReg::kTypeGp16, //!< GPW register.
|
//! Low GPB register (AL, BL, CL, DL, ...).
|
||||||
kTypeGpd = BaseReg::kTypeGp32, //!< GPD register.
|
kTypeGpbLo = BaseReg::kTypeGp8Lo,
|
||||||
kTypeGpq = BaseReg::kTypeGp64, //!< GPQ register (64-bit).
|
//! High GPB register (AH, BH, CH, DH only).
|
||||||
kTypeXmm = BaseReg::kTypeVec128, //!< XMM register (SSE+).
|
kTypeGpbHi = BaseReg::kTypeGp8Hi,
|
||||||
kTypeYmm = BaseReg::kTypeVec256, //!< YMM register (AVX+).
|
//! GPW register.
|
||||||
kTypeZmm = BaseReg::kTypeVec512, //!< ZMM register (AVX512+).
|
kTypeGpw = BaseReg::kTypeGp16,
|
||||||
kTypeMm = BaseReg::kTypeOther0, //!< MMX register.
|
//! GPD register.
|
||||||
kTypeKReg = BaseReg::kTypeOther1, //!< K register (AVX512+).
|
kTypeGpd = BaseReg::kTypeGp32,
|
||||||
kTypeSReg = BaseReg::kTypeCustom+0, //!< Segment register (None, ES, CS, SS, DS, FS, GS).
|
//! GPQ register (64-bit).
|
||||||
kTypeCReg = BaseReg::kTypeCustom+1, //!< Control register (CR).
|
kTypeGpq = BaseReg::kTypeGp64,
|
||||||
kTypeDReg = BaseReg::kTypeCustom+2, //!< Debug register (DR).
|
//! XMM register (SSE+).
|
||||||
kTypeSt = BaseReg::kTypeCustom+3, //!< FPU (x87) register.
|
kTypeXmm = BaseReg::kTypeVec128,
|
||||||
kTypeBnd = BaseReg::kTypeCustom+4, //!< Bound register (BND).
|
//! YMM register (AVX+).
|
||||||
kTypeRip = BaseReg::kTypeIP, //!< Instruction pointer (EIP, RIP).
|
kTypeYmm = BaseReg::kTypeVec256,
|
||||||
kTypeCount = BaseReg::kTypeCustom+5 //!< Count of register types.
|
//! ZMM register (AVX512+).
|
||||||
|
kTypeZmm = BaseReg::kTypeVec512,
|
||||||
|
//! MMX register.
|
||||||
|
kTypeMm = BaseReg::kTypeOther0,
|
||||||
|
//! K register (AVX512+).
|
||||||
|
kTypeKReg = BaseReg::kTypeOther1,
|
||||||
|
//! Instruction pointer (EIP, RIP).
|
||||||
|
kTypeRip = BaseReg::kTypeIP,
|
||||||
|
//! Segment register (None, ES, CS, SS, DS, FS, GS).
|
||||||
|
kTypeSReg = BaseReg::kTypeCustom + 0,
|
||||||
|
//! Control register (CR).
|
||||||
|
kTypeCReg = BaseReg::kTypeCustom + 1,
|
||||||
|
//! Debug register (DR).
|
||||||
|
kTypeDReg = BaseReg::kTypeCustom + 2,
|
||||||
|
//! FPU (x87) register.
|
||||||
|
kTypeSt = BaseReg::kTypeCustom + 3,
|
||||||
|
//! Bound register (BND).
|
||||||
|
kTypeBnd = BaseReg::kTypeCustom + 4,
|
||||||
|
//! TMM register (AMX_TILE)
|
||||||
|
kTypeTmm = BaseReg::kTypeCustom + 5,
|
||||||
|
|
||||||
|
//! Count of register types.
|
||||||
|
kTypeCount = BaseReg::kTypeCustom + 6
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Register group.
|
//! Register group.
|
||||||
enum RegGroup : uint32_t {
|
enum RegGroup : uint32_t {
|
||||||
kGroupGp = BaseReg::kGroupGp, //!< GP register group or none (universal).
|
//! GP register group or none (universal).
|
||||||
kGroupVec = BaseReg::kGroupVec, //!< XMM|YMM|ZMM register group (universal).
|
kGroupGp = BaseReg::kGroupGp,
|
||||||
kGroupMm = BaseReg::kGroupOther0, //!< MMX register group (legacy).
|
//! XMM|YMM|ZMM register group (universal).
|
||||||
kGroupKReg = BaseReg::kGroupOther1, //!< K register group.
|
kGroupVec = BaseReg::kGroupVec,
|
||||||
|
//! MMX register group (legacy).
|
||||||
|
kGroupMm = BaseReg::kGroupOther0,
|
||||||
|
//! K register group.
|
||||||
|
kGroupKReg = BaseReg::kGroupOther1,
|
||||||
|
|
||||||
// These are not managed by BaseCompiler nor used by Func-API:
|
// These are not managed by Compiler nor used by Func-API:
|
||||||
kGroupSReg = BaseReg::kGroupVirt+0, //!< Segment register group.
|
|
||||||
kGroupCReg = BaseReg::kGroupVirt+1, //!< Control register group.
|
//! Segment register group.
|
||||||
kGroupDReg = BaseReg::kGroupVirt+2, //!< Debug register group.
|
kGroupSReg = BaseReg::kGroupVirt+0,
|
||||||
kGroupSt = BaseReg::kGroupVirt+3, //!< FPU register group.
|
//! Control register group.
|
||||||
kGroupBnd = BaseReg::kGroupVirt+4, //!< Bound register group.
|
kGroupCReg = BaseReg::kGroupVirt+1,
|
||||||
kGroupRip = BaseReg::kGroupVirt+5, //!< Instrucion pointer (IP).
|
//! Debug register group.
|
||||||
kGroupCount //!< Count of all register groups.
|
kGroupDReg = BaseReg::kGroupVirt+2,
|
||||||
|
//! FPU register group.
|
||||||
|
kGroupSt = BaseReg::kGroupVirt+3,
|
||||||
|
//! Bound register group.
|
||||||
|
kGroupBnd = BaseReg::kGroupVirt+4,
|
||||||
|
//! TMM register group.
|
||||||
|
kGroupTmm = BaseReg::kGroupVirt+5,
|
||||||
|
//! Instrucion pointer (IP).
|
||||||
|
kGroupRip = BaseReg::kGroupVirt+6,
|
||||||
|
|
||||||
|
//! Count of all register groups.
|
||||||
|
kGroupCount
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Tests whether the register is a GPB register (8-bit).
|
//! Tests whether the register is a GPB register (8-bit).
|
||||||
@@ -221,6 +260,8 @@ public:
|
|||||||
constexpr bool isSt() const noexcept { return hasSignature(RegTraits<kTypeSt>::kSignature); }
|
constexpr bool isSt() const noexcept { return hasSignature(RegTraits<kTypeSt>::kSignature); }
|
||||||
//! Tests whether the register is a bound register.
|
//! Tests whether the register is a bound register.
|
||||||
constexpr bool isBnd() const noexcept { return hasSignature(RegTraits<kTypeBnd>::kSignature); }
|
constexpr bool isBnd() const noexcept { return hasSignature(RegTraits<kTypeBnd>::kSignature); }
|
||||||
|
//! Tests whether the register is a TMM register.
|
||||||
|
constexpr bool isTmm() const noexcept { return hasSignature(RegTraits<kTypeTmm>::kSignature); }
|
||||||
//! Tests whether the register is RIP.
|
//! Tests whether the register is RIP.
|
||||||
constexpr bool isRip() const noexcept { return hasSignature(RegTraits<kTypeRip>::kSignature); }
|
constexpr bool isRip() const noexcept { return hasSignature(RegTraits<kTypeRip>::kSignature); }
|
||||||
|
|
||||||
@@ -281,6 +322,7 @@ public:
|
|||||||
static inline bool isDReg(const Operand_& op) noexcept { return op.as<Reg>().isDReg(); }
|
static inline bool isDReg(const Operand_& op) noexcept { return op.as<Reg>().isDReg(); }
|
||||||
static inline bool isSt(const Operand_& op) noexcept { return op.as<Reg>().isSt(); }
|
static inline bool isSt(const Operand_& op) noexcept { return op.as<Reg>().isSt(); }
|
||||||
static inline bool isBnd(const Operand_& op) noexcept { return op.as<Reg>().isBnd(); }
|
static inline bool isBnd(const Operand_& op) noexcept { return op.as<Reg>().isBnd(); }
|
||||||
|
static inline bool isTmm(const Operand_& op) noexcept { return op.as<Reg>().isTmm(); }
|
||||||
static inline bool isRip(const Operand_& op) noexcept { return op.as<Reg>().isRip(); }
|
static inline bool isRip(const Operand_& op) noexcept { return op.as<Reg>().isRip(); }
|
||||||
|
|
||||||
static inline bool isGpb(const Operand_& op, uint32_t rId) noexcept { return isGpb(op) & (op.id() == rId); }
|
static inline bool isGpb(const Operand_& op, uint32_t rId) noexcept { return isGpb(op) & (op.id() == rId); }
|
||||||
@@ -299,6 +341,7 @@ public:
|
|||||||
static inline bool isDReg(const Operand_& op, uint32_t rId) noexcept { return isDReg(op) & (op.id() == rId); }
|
static inline bool isDReg(const Operand_& op, uint32_t rId) noexcept { return isDReg(op) & (op.id() == rId); }
|
||||||
static inline bool isSt(const Operand_& op, uint32_t rId) noexcept { return isSt(op) & (op.id() == rId); }
|
static inline bool isSt(const Operand_& op, uint32_t rId) noexcept { return isSt(op) & (op.id() == rId); }
|
||||||
static inline bool isBnd(const Operand_& op, uint32_t rId) noexcept { return isBnd(op) & (op.id() == rId); }
|
static inline bool isBnd(const Operand_& op, uint32_t rId) noexcept { return isBnd(op) & (op.id() == rId); }
|
||||||
|
static inline bool isTmm(const Operand_& op, uint32_t rId) noexcept { return isTmm(op) & (op.id() == rId); }
|
||||||
static inline bool isRip(const Operand_& op, uint32_t rId) noexcept { return isRip(op) & (op.id() == rId); }
|
static inline bool isRip(const Operand_& op, uint32_t rId) noexcept { return isRip(op) & (op.id() == rId); }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -368,19 +411,26 @@ class SReg : public Reg {
|
|||||||
|
|
||||||
//! X86 segment id.
|
//! X86 segment id.
|
||||||
enum Id : uint32_t {
|
enum Id : uint32_t {
|
||||||
kIdNone = 0, //!< No segment (default).
|
//! No segment (default).
|
||||||
kIdEs = 1, //!< ES segment.
|
kIdNone = 0,
|
||||||
kIdCs = 2, //!< CS segment.
|
//! ES segment.
|
||||||
kIdSs = 3, //!< SS segment.
|
kIdEs = 1,
|
||||||
kIdDs = 4, //!< DS segment.
|
//! CS segment.
|
||||||
kIdFs = 5, //!< FS segment.
|
kIdCs = 2,
|
||||||
kIdGs = 6, //!< GS segment.
|
//! SS segment.
|
||||||
|
kIdSs = 3,
|
||||||
|
//! DS segment.
|
||||||
|
kIdDs = 4,
|
||||||
|
//! FS segment.
|
||||||
|
kIdFs = 5,
|
||||||
|
//! GS segment.
|
||||||
|
kIdGs = 6,
|
||||||
|
|
||||||
//! Count of segment registers supported by AsmJit.
|
//! Count of X86 segment registers supported by AsmJit.
|
||||||
//!
|
//!
|
||||||
//! \note X86 architecture has 6 segment registers - ES, CS, SS, DS, FS, GS.
|
//! \note X86 architecture has 6 segment registers - ES, CS, SS, DS, FS, GS.
|
||||||
//! X64 architecture lowers them down to just FS and GS. AsmJit supports 7
|
//! X64 architecture lowers them down to just FS and GS. AsmJit supports 7
|
||||||
//! segment registers - all addressable in both and X64 modes and one
|
//! segment registers - all addressable in both X86 and X64 modes and one
|
||||||
//! extra called `SReg::kIdNone`, which is AsmJit specific and means that
|
//! extra called `SReg::kIdNone`, which is AsmJit specific and means that
|
||||||
//! there is no segment register specified.
|
//! there is no segment register specified.
|
||||||
kIdCount = 7
|
kIdCount = 7
|
||||||
@@ -433,6 +483,8 @@ class DReg : public Reg { ASMJIT_DEFINE_FINAL_REG(DReg, Reg, RegTraits<kTypeDReg
|
|||||||
class St : public Reg { ASMJIT_DEFINE_FINAL_REG(St, Reg, RegTraits<kTypeSt>) };
|
class St : public Reg { ASMJIT_DEFINE_FINAL_REG(St, Reg, RegTraits<kTypeSt>) };
|
||||||
//! 128-bit BND register (BND+).
|
//! 128-bit BND register (BND+).
|
||||||
class Bnd : public Reg { ASMJIT_DEFINE_FINAL_REG(Bnd, Reg, RegTraits<kTypeBnd>) };
|
class Bnd : public Reg { ASMJIT_DEFINE_FINAL_REG(Bnd, Reg, RegTraits<kTypeBnd>) };
|
||||||
|
//! 8192-bit TMM register (AMX).
|
||||||
|
class Tmm : public Reg { ASMJIT_DEFINE_FINAL_REG(Tmm, Reg, RegTraits<kTypeTmm>) };
|
||||||
//! RIP register (X86).
|
//! RIP register (X86).
|
||||||
class Rip : public Reg { ASMJIT_DEFINE_FINAL_REG(Rip, Reg, RegTraits<kTypeRip>) };
|
class Rip : public Reg { ASMJIT_DEFINE_FINAL_REG(Rip, Reg, RegTraits<kTypeRip>) };
|
||||||
|
|
||||||
@@ -489,6 +541,8 @@ static constexpr DReg dr(uint32_t rId) noexcept { return DReg(rId); }
|
|||||||
static constexpr St st(uint32_t rId) noexcept { return St(rId); }
|
static constexpr St st(uint32_t rId) noexcept { return St(rId); }
|
||||||
//! Creates a 128-bit bound register operand.
|
//! Creates a 128-bit bound register operand.
|
||||||
static constexpr Bnd bnd(uint32_t rId) noexcept { return Bnd(rId); }
|
static constexpr Bnd bnd(uint32_t rId) noexcept { return Bnd(rId); }
|
||||||
|
//! Creates a TMM register operand.
|
||||||
|
static constexpr Tmm tmm(uint32_t rId) noexcept { return Tmm(rId); }
|
||||||
|
|
||||||
static constexpr Gp al = Gp(GpbLo::kSignature, Gp::kIdAx);
|
static constexpr Gp al = Gp(GpbLo::kSignature, Gp::kIdAx);
|
||||||
static constexpr Gp bl = Gp(GpbLo::kSignature, Gp::kIdBx);
|
static constexpr Gp bl = Gp(GpbLo::kSignature, Gp::kIdBx);
|
||||||
@@ -736,6 +790,15 @@ static constexpr Bnd bnd1 = Bnd(1);
|
|||||||
static constexpr Bnd bnd2 = Bnd(2);
|
static constexpr Bnd bnd2 = Bnd(2);
|
||||||
static constexpr Bnd bnd3 = Bnd(3);
|
static constexpr Bnd bnd3 = Bnd(3);
|
||||||
|
|
||||||
|
static constexpr Tmm tmm0 = Tmm(0);
|
||||||
|
static constexpr Tmm tmm1 = Tmm(1);
|
||||||
|
static constexpr Tmm tmm2 = Tmm(2);
|
||||||
|
static constexpr Tmm tmm3 = Tmm(3);
|
||||||
|
static constexpr Tmm tmm4 = Tmm(4);
|
||||||
|
static constexpr Tmm tmm5 = Tmm(5);
|
||||||
|
static constexpr Tmm tmm6 = Tmm(6);
|
||||||
|
static constexpr Tmm tmm7 = Tmm(7);
|
||||||
|
|
||||||
static constexpr Rip rip = Rip(0);
|
static constexpr Rip rip = Rip(0);
|
||||||
|
|
||||||
#ifndef _DOXYGEN
|
#ifndef _DOXYGEN
|
||||||
|
|||||||
@@ -221,6 +221,9 @@ class GenUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (dbInst.attributes.Tsib)
|
||||||
|
f.Tsib = true;
|
||||||
|
|
||||||
if (dbInst.vsibReg)
|
if (dbInst.vsibReg)
|
||||||
f.Vsib = true;
|
f.Vsib = true;
|
||||||
|
|
||||||
@@ -509,7 +512,9 @@ class X86TableGen extends core.TableGen {
|
|||||||
String(inst.encoding ).padEnd(19) + ", " +
|
String(inst.encoding ).padEnd(19) + ", " +
|
||||||
String(inst.opcode0 ).padEnd(26) + ", " +
|
String(inst.opcode0 ).padEnd(26) + ", " +
|
||||||
String(inst.opcode1 ).padEnd(26) + ", " +
|
String(inst.opcode1 ).padEnd(26) + ", " +
|
||||||
String("0" ).padEnd( 4) + ", " +
|
String("0" ).padEnd( 3) + ", " +
|
||||||
|
String("0" ).padEnd( 3) + ", " +
|
||||||
|
String("0" ).padEnd( 5) + ", " +
|
||||||
String("0" ).padEnd( 3) + ", " +
|
String("0" ).padEnd( 3) + ", " +
|
||||||
String("0" ).padEnd( 3) + "),\n";
|
String("0" ).padEnd( 3) + "),\n";
|
||||||
}
|
}
|
||||||
@@ -930,6 +935,7 @@ const OpToAsmJitOp = {
|
|||||||
"dreg" : "F(DReg)",
|
"dreg" : "F(DReg)",
|
||||||
"st" : "F(St)",
|
"st" : "F(St)",
|
||||||
"bnd" : "F(Bnd)",
|
"bnd" : "F(Bnd)",
|
||||||
|
"tmm" : "F(Tmm)",
|
||||||
|
|
||||||
"mem" : "F(Mem)",
|
"mem" : "F(Mem)",
|
||||||
"vm" : "F(Vm)",
|
"vm" : "F(Vm)",
|
||||||
@@ -1096,7 +1102,8 @@ class OSignature {
|
|||||||
case "mm" :
|
case "mm" :
|
||||||
case "xmm" :
|
case "xmm" :
|
||||||
case "ymm" :
|
case "ymm" :
|
||||||
case "zmm" : mFlags[k] = true; break;
|
case "zmm" :
|
||||||
|
case "tmm" : mFlags[k] = true; break;
|
||||||
|
|
||||||
case "m8" :
|
case "m8" :
|
||||||
case "m16" :
|
case "m16" :
|
||||||
@@ -1108,8 +1115,9 @@ class OSignature {
|
|||||||
case "m256" :
|
case "m256" :
|
||||||
case "m512" :
|
case "m512" :
|
||||||
case "m1024" : mFlags.mem = true; mMemFlags[k] = true; break;
|
case "m1024" : mFlags.mem = true; mMemFlags[k] = true; break;
|
||||||
case "mib" : mFlags.mem = true; mMemFlags.mib = true; break;
|
case "mib" : mFlags.mem = true; mMemFlags.mib = true; break;
|
||||||
case "mem" : mFlags.mem = true; mMemFlags.mAny = true; break;
|
case "mem" : mFlags.mem = true; mMemFlags.mAny = true; break;
|
||||||
|
case "tmem" : mFlags.mem = true; mMemFlags.mAny = true; break;
|
||||||
|
|
||||||
case "memBase" : mFlags.mem = true; mMemFlags.memBase = true; break;
|
case "memBase" : mFlags.mem = true; mMemFlags.memBase = true; break;
|
||||||
case "memDS" : mFlags.mem = true; mMemFlags.memDS = true; break;
|
case "memDS" : mFlags.mem = true; mMemFlags.memDS = true; break;
|
||||||
@@ -1814,8 +1822,11 @@ class InstRWInfoTable extends core.Task {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super("InstRWInfoTable");
|
super("InstRWInfoTable");
|
||||||
|
|
||||||
this.rwInfoIndex = [];
|
this.rwInfoIndexA = [];
|
||||||
this.rwInfoTable = new IndexedArray();
|
this.rwInfoIndexB = [];
|
||||||
|
this.rwInfoTableA = new IndexedArray();
|
||||||
|
this.rwInfoTableB = new IndexedArray();
|
||||||
|
|
||||||
this.rmInfoTable = new IndexedArray();
|
this.rmInfoTable = new IndexedArray();
|
||||||
this.opInfoTable = new IndexedArray();
|
this.opInfoTable = new IndexedArray();
|
||||||
|
|
||||||
@@ -1954,21 +1965,30 @@ class InstRWInfoTable extends core.Task {
|
|||||||
CxxUtils.struct(...(rwOpsIndex.map(function(item) { return String(item).padEnd(2); })))
|
CxxUtils.struct(...(rwOpsIndex.map(function(item) { return String(item).padEnd(2); })))
|
||||||
);
|
);
|
||||||
|
|
||||||
this.rwInfoIndex.push(this.rwInfoTable.addIndexed(rwData));
|
if (i == 0)
|
||||||
|
this.rwInfoIndexA.push(this.rwInfoTableA.addIndexed(rwData));
|
||||||
|
else
|
||||||
|
this.rwInfoIndexB.push(this.rwInfoTableB.addIndexed(rwData));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var s = "";
|
var s = "";
|
||||||
s += "const uint8_t InstDB::rwInfoIndex[Inst::_kIdCount * 2] = {\n" + StringUtils.format(this.rwInfoIndex, kIndent, -1) + "\n};\n";
|
s += "const uint8_t InstDB::rwInfoIndexA[Inst::_kIdCount] = {\n" + StringUtils.format(this.rwInfoIndexA, kIndent, -1) + "\n};\n";
|
||||||
s += "\n";
|
s += "\n";
|
||||||
s += "const InstDB::RWInfo InstDB::rwInfo[] = {\n" + StringUtils.format(this.rwInfoTable, kIndent, true) + "\n};\n";
|
s += "const uint8_t InstDB::rwInfoIndexB[Inst::_kIdCount] = {\n" + StringUtils.format(this.rwInfoIndexB, kIndent, -1) + "\n};\n";
|
||||||
|
s += "\n";
|
||||||
|
s += "const InstDB::RWInfo InstDB::rwInfoA[] = {\n" + StringUtils.format(this.rwInfoTableA, kIndent, true) + "\n};\n";
|
||||||
|
s += "\n";
|
||||||
|
s += "const InstDB::RWInfo InstDB::rwInfoB[] = {\n" + StringUtils.format(this.rwInfoTableB, kIndent, true) + "\n};\n";
|
||||||
s += "\n";
|
s += "\n";
|
||||||
s += "const InstDB::RWInfoOp InstDB::rwInfoOp[] = {\n" + StringUtils.format(this.opInfoTable, kIndent, true) + "\n};\n";
|
s += "const InstDB::RWInfoOp InstDB::rwInfoOp[] = {\n" + StringUtils.format(this.opInfoTable, kIndent, true) + "\n};\n";
|
||||||
s += "\n";
|
s += "\n";
|
||||||
s += "const InstDB::RWInfoRm InstDB::rwInfoRm[] = {\n" + StringUtils.format(this.rmInfoTable, kIndent, true) + "\n};\n";
|
s += "const InstDB::RWInfoRm InstDB::rwInfoRm[] = {\n" + StringUtils.format(this.rmInfoTable, kIndent, true) + "\n};\n";
|
||||||
|
|
||||||
const size = this.rwInfoIndex.length +
|
const size = this.rwInfoIndexA.length +
|
||||||
this.rwInfoTable.length * 8 +
|
this.rwInfoIndexB.length +
|
||||||
|
this.rwInfoTableA.length * 8 +
|
||||||
|
this.rwInfoTableB.length * 8 +
|
||||||
this.rmInfoTable.length * 4 +
|
this.rmInfoTable.length * 4 +
|
||||||
this.opInfoTable.length * 24;
|
this.opInfoTable.length * 24;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user