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:
|
||||
* [ ] 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:
|
||||
* [ ] ARM/Thumb/AArch64 support.
|
||||
|
||||
|
||||
@@ -789,7 +789,7 @@ Error BaseBuilder::comment(const char* data, size_t size) {
|
||||
// [asmjit::BaseBuilder - Serialize]
|
||||
// ============================================================================
|
||||
|
||||
Error BaseBuilder::serialize(BaseEmitter* dst) {
|
||||
Error BaseBuilder::serializeTo(BaseEmitter* dst) {
|
||||
Error err = kErrorOk;
|
||||
BaseNode* node_ = _firstNode;
|
||||
|
||||
|
||||
@@ -357,7 +357,7 @@ public:
|
||||
//! Although not explicitly required the emitter will most probably be of
|
||||
//! Assembler type. The reason is that there is no known use of serializing
|
||||
//! 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
|
||||
ASMJIT_DEPRECATED("Use serializeTo() instead, serialize() is now also an instruction.")
|
||||
inline Error serialize(BaseEmitter* dst) {
|
||||
return serializeTo(dst);
|
||||
}
|
||||
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
ASMJIT_DEPRECATED("Use Formatter::formatNodeList(sb, formatFlags, builder)")
|
||||
inline Error dump(String& sb, uint32_t formatFlags = 0) const noexcept {
|
||||
|
||||
@@ -674,7 +674,7 @@ public:
|
||||
kTypeIP = 15,
|
||||
//! Start of platform dependent register types (must be honored).
|
||||
kTypeCustom = 16,
|
||||
//! Maximum possible register id of all architectures.
|
||||
//! Maximum possible register type value.
|
||||
kTypeMax = 31
|
||||
};
|
||||
|
||||
|
||||
@@ -669,6 +669,13 @@ ASMJIT_FAVOR_SPEED Error Assembler::_emit(uint32_t instId, const Operand_& o0, c
|
||||
// [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) {
|
||||
case InstDB::kEncodingNone:
|
||||
goto EmitDone;
|
||||
@@ -854,6 +861,32 @@ CaseX86M_GPB_MulDiv:
|
||||
}
|
||||
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:
|
||||
if (isign3 == ENC_OPS1(Reg)) {
|
||||
rbReg = o0.id();
|
||||
@@ -2767,6 +2800,10 @@ CaseExtRm:
|
||||
case InstDB::kEncodingVexOp:
|
||||
goto EmitVexEvexOp;
|
||||
|
||||
case InstDB::kEncodingVexOpMod:
|
||||
rbReg = 0;
|
||||
goto EmitVexEvexR;
|
||||
|
||||
case InstDB::kEncodingVexKmov:
|
||||
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
||||
opReg = o0.id();
|
||||
@@ -3007,6 +3044,33 @@ CaseVexRvm_R:
|
||||
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: {
|
||||
opcode |= x86OpcodeLBySize(o0.size() | o1.size());
|
||||
ASMJIT_FALLTHROUGH;
|
||||
@@ -3598,6 +3662,49 @@ CaseVexVmi_AfterImm:
|
||||
}
|
||||
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;
|
||||
@@ -3628,6 +3735,10 @@ EmitX86Op:
|
||||
writer.emitImmediate(uint64_t(immValue), immSize);
|
||||
goto EmitDone;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Emit - X86 - Opcode + Reg]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
EmitX86OpReg:
|
||||
// Emit mandatory instruction prefix.
|
||||
writer.emitPP(opcode.v);
|
||||
@@ -3649,8 +3760,11 @@ EmitX86OpReg:
|
||||
writer.emitImmediate(uint64_t(immValue), immSize);
|
||||
goto EmitDone;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Emit - X86 - Opcode with implicit <mem> operand]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
EmitX86OpImplicitMem:
|
||||
// NOTE: Don't change the emit order here, it's compatible with KeyStone/LLVM.
|
||||
rmInfo = x86MemInfo[rmRel->as<Mem>().baseAndIndexTypes()];
|
||||
if (ASMJIT_UNLIKELY(rmRel->as<Mem>().hasOffset() || (rmInfo & kX86MemInfo_Index)))
|
||||
goto InvalidInstruction;
|
||||
@@ -3667,19 +3781,26 @@ EmitX86OpImplicitMem:
|
||||
writer.emit8If(rex | kX86ByteRex, rex != 0);
|
||||
}
|
||||
|
||||
// Emit override prefixes.
|
||||
writer.emitSegmentOverride(rmRel->as<Mem>().segmentId());
|
||||
writer.emitAddressOverride((rmInfo & _addressOverrideMask()) != 0);
|
||||
|
||||
// Emit instruction opcodes.
|
||||
writer.emitMMAndOpcode(opcode.v);
|
||||
|
||||
// Emit immediate value.
|
||||
writer.emitImmediate(uint64_t(immValue), immSize);
|
||||
goto EmitDone;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Emit - X86 - Opcode /r - register]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
EmitX86R:
|
||||
// Mandatory instruction prefix.
|
||||
writer.emitPP(opcode.v);
|
||||
|
||||
// Rex prefix (64-bit only).
|
||||
// Emit REX prefix (64-bit only).
|
||||
{
|
||||
uint32_t rex = opcode.extractRex(options) |
|
||||
((opReg & 0x08) >> 1) | // REX.R (0x04).
|
||||
@@ -3694,32 +3815,80 @@ EmitX86R:
|
||||
rbReg &= 0x07;
|
||||
}
|
||||
|
||||
// Instruction opcodes.
|
||||
// Emit instruction opcodes.
|
||||
writer.emitMMAndOpcode(opcode.v);
|
||||
// ModR.
|
||||
|
||||
// Emit ModR.
|
||||
writer.emit8(x86EncodeMod(3, opReg, rbReg));
|
||||
// Emit immediate value.
|
||||
|
||||
writer.emitImmediate(uint64_t(immValue), immSize);
|
||||
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:
|
||||
// `rmRel` operand must be memory.
|
||||
ASMJIT_ASSERT(rmRel != nullptr);
|
||||
ASMJIT_ASSERT(rmRel->opType() == Operand::kOpMem);
|
||||
ASMJIT_ASSERT((opcode & Opcode::kCDSHL_Mask) == 0);
|
||||
|
||||
// Emit override prefixes.
|
||||
rmInfo = x86MemInfo[rmRel->as<Mem>().baseAndIndexTypes()];
|
||||
writer.emitSegmentOverride(rmRel->as<Mem>().segmentId());
|
||||
|
||||
memOpAOMark = writer.cursor();
|
||||
writer.emitAddressOverride((rmInfo & _addressOverrideMask()) != 0);
|
||||
|
||||
// Mandatory instruction prefix.
|
||||
// Emit mandatory instruction prefix.
|
||||
writer.emitPP(opcode.v);
|
||||
|
||||
// Emit REX prefix (64-bit only).
|
||||
rbReg = rmRel->as<Mem>().baseId();
|
||||
rxReg = rmRel->as<Mem>().indexId();
|
||||
|
||||
// REX prefix (64-bit only).
|
||||
{
|
||||
uint32_t rex;
|
||||
|
||||
@@ -3738,8 +3907,9 @@ EmitX86M:
|
||||
opReg &= 0x07;
|
||||
}
|
||||
|
||||
// Instruction opcodes.
|
||||
// Emit instruction opcodes.
|
||||
writer.emitMMAndOpcode(opcode.v);
|
||||
|
||||
// ... Fall through ...
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
@@ -3754,25 +3924,28 @@ EmitModSib:
|
||||
relOffset = rmRel->as<Mem>().offsetLo32();
|
||||
|
||||
uint32_t mod = x86EncodeMod(0, opReg, rbReg);
|
||||
if (rbReg == Gp::kIdSp) {
|
||||
// [XSP|R12].
|
||||
if (relOffset == 0) {
|
||||
bool forceSIB = commonInfo->isTsibOp();
|
||||
|
||||
if (rbReg == Gp::kIdSp || forceSIB) {
|
||||
// TSIB or [XSP|R12].
|
||||
mod = (mod & 0xF8u) | 0x04u;
|
||||
if (rbReg != Gp::kIdBp && relOffset == 0) {
|
||||
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 {
|
||||
uint32_t cdShift = (opcode & Opcode::kCDSHL_Mask) >> Opcode::kCDSHL_Shift;
|
||||
int32_t cdOffset = relOffset >> cdShift;
|
||||
|
||||
if (Support::isInt8(cdOffset) && relOffset == int32_t(uint32_t(cdOffset) << cdShift)) {
|
||||
writer.emit8(mod + 0x40); // <- MOD(1, opReg, rbReg).
|
||||
writer.emit8(x86EncodeSib(0, 4, 4));
|
||||
writer.emit8(x86EncodeSib(0, 4, rbReg));
|
||||
writer.emit8(cdOffset & 0xFF);
|
||||
}
|
||||
else {
|
||||
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));
|
||||
}
|
||||
}
|
||||
@@ -4144,7 +4317,7 @@ EmitFpuOp:
|
||||
goto EmitDone;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Emit - VEX / EVEX]
|
||||
// [Emit - VEX|EVEX]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
EmitVexEvexOp:
|
||||
@@ -4181,6 +4354,10 @@ EmitVexEvexOp:
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Emit - VEX|EVEX - /r (Register)]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
EmitVexEvexR:
|
||||
{
|
||||
// Construct `x` - a complete EVEX|VEX prefix.
|
||||
@@ -4288,6 +4465,10 @@ EmitVexEvexR:
|
||||
}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Emit - VEX|EVEX - /r (Memory)]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
EmitVexEvexM:
|
||||
ASMJIT_ASSERT(rmRel != nullptr);
|
||||
ASMJIT_ASSERT(rmRel->opType() == Operand::kOpMem);
|
||||
@@ -4623,6 +4804,7 @@ EmitDone:
|
||||
ERROR_HANDLER(InvalidAddressIndex)
|
||||
ERROR_HANDLER(InvalidAddress64Bit)
|
||||
ERROR_HANDLER(InvalidDisplacement)
|
||||
ERROR_HANDLER(InvalidPhysId)
|
||||
ERROR_HANDLER(InvalidSegment)
|
||||
ERROR_HANDLER(InvalidImmediate)
|
||||
ERROR_HANDLER(OperandSizeMismatch)
|
||||
|
||||
@@ -48,7 +48,7 @@ Error Builder::finalize() {
|
||||
Assembler a(_code);
|
||||
a.addEncodingOptions(encodingOptions());
|
||||
a.addValidationOptions(validationOptions());
|
||||
return serialize(&a);
|
||||
return serializeTo(&a);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
|
||||
@@ -49,7 +49,7 @@ Error Compiler::finalize() {
|
||||
Assembler a(_code);
|
||||
a.addEncodingOptions(encodingOptions());
|
||||
a.addValidationOptions(validationOptions());
|
||||
return serialize(&a);
|
||||
return serializeTo(&a);
|
||||
}
|
||||
// ============================================================================
|
||||
// [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, 28)) features.add(Features::kMOVDIR64B);
|
||||
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, 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.
|
||||
if (features.hasHLE() || features.hasRTM())
|
||||
@@ -330,7 +335,7 @@ ASMJIT_FAVOR_SIZE void detectCpu(CpuInfo& cpu) noexcept {
|
||||
uint32_t i = maxId;
|
||||
|
||||
// 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
|
||||
// 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, 22)) features.add(Features::kMMX2);
|
||||
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, 31)) features.add(Features::k3DNOW);
|
||||
if (bitTest(regs.edx, 31)) features.add(Features::kPREFETCHW);
|
||||
|
||||
if (cpu.hasFeature(Features::kAVX)) {
|
||||
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.edx;
|
||||
|
||||
// Go directly to the last one.
|
||||
// Go directly to the next one we are interested in.
|
||||
if (i == 0x80000004u) i = 0x80000008u - 1;
|
||||
break;
|
||||
|
||||
case 0x80000008u:
|
||||
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;
|
||||
}
|
||||
} while (++i <= maxId);
|
||||
|
||||
@@ -52,6 +52,9 @@ public:
|
||||
kADX, //!< CPU has ADX (multi-precision add-carry instruction extensions).
|
||||
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].
|
||||
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).
|
||||
kAVX2, //!< CPU has AVX2 (advanced vector extensions 2).
|
||||
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].
|
||||
kLWP, //!< CPU has LWP (lightweight profiling) [AMD].
|
||||
kLZCNT, //!< CPU has LZCNT (LZCNT instruction).
|
||||
kMCOMMIT, //!< CPU has MCOMMIT (MCOMMIT instruction).
|
||||
kMMX, //!< CPU has MMX (MMX base instructions).
|
||||
kMMX2, //!< CPU has MMX2 (MMX extensions or MMX2).
|
||||
kMONITOR, //!< CPU has MONITOR (MONITOR/MWAIT instructions).
|
||||
@@ -116,16 +120,19 @@ public:
|
||||
kPREFETCHW, //!< CPU has PREFETCHW.
|
||||
kPREFETCHWT1, //!< CPU has PREFETCHWT1.
|
||||
kRDPID, //!< CPU has RDPID.
|
||||
kRDPRU, //!< CPU has RDPRU.
|
||||
kRDRAND, //!< CPU has RDRAND.
|
||||
kRDSEED, //!< CPU has RDSEED.
|
||||
kRDTSC, //!< CPU has RDTSC.
|
||||
kRDTSCP, //!< CPU has RDTSCP.
|
||||
kRTM, //!< CPU has RTM.
|
||||
kSERIALIZE, //!< CPU has SERIALIZE.
|
||||
kSHA, //!< CPU has SHA (SHA-1 and SHA-256 instructions).
|
||||
kSKINIT, //!< CPU has SKINIT (SKINIT/STGI instructions) [AMD].
|
||||
kSMAP, //!< CPU has SMAP (supervisor-mode access prevention).
|
||||
kSMEP, //!< CPU has SMEP (supervisor-mode execution prevention).
|
||||
kSMX, //!< CPU has SMX (safer mode extensions).
|
||||
kSNP, //!< CPU has SNP.
|
||||
kSSE, //!< CPU has SSE.
|
||||
kSSE2, //!< CPU has SSE2.
|
||||
kSSE3, //!< CPU has SSE3.
|
||||
@@ -136,6 +143,7 @@ public:
|
||||
kSVM, //!< CPU has SVM (virtualization) [AMD].
|
||||
kTBM, //!< CPU has TBM (trailing bit manipulation) [AMD].
|
||||
kTSX, //!< CPU has TSX.
|
||||
kTSXLDTRK, //!< CPU has TSXLDTRK.
|
||||
kVAES, //!< CPU has VAES (vector AES 256|512 bit support).
|
||||
kVMX, //!< CPU has VMX (virtualization) [INTEL].
|
||||
kVPCLMULQDQ, //!< CPU has VPCLMULQDQ (vector PCLMULQDQ 256|512-bit support).
|
||||
@@ -183,6 +191,9 @@ public:
|
||||
ASMJIT_X86_FEATURE(ADX)
|
||||
ASMJIT_X86_FEATURE(AESNI)
|
||||
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(AVX2)
|
||||
ASMJIT_X86_FEATURE(AVX512_4FMAPS)
|
||||
@@ -229,6 +240,7 @@ public:
|
||||
ASMJIT_X86_FEATURE(LAHFSAHF)
|
||||
ASMJIT_X86_FEATURE(LWP)
|
||||
ASMJIT_X86_FEATURE(LZCNT)
|
||||
ASMJIT_X86_FEATURE(MCOMMIT)
|
||||
ASMJIT_X86_FEATURE(MMX)
|
||||
ASMJIT_X86_FEATURE(MMX2)
|
||||
ASMJIT_X86_FEATURE(MONITOR)
|
||||
@@ -247,16 +259,19 @@ public:
|
||||
ASMJIT_X86_FEATURE(PREFETCHW)
|
||||
ASMJIT_X86_FEATURE(PREFETCHWT1)
|
||||
ASMJIT_X86_FEATURE(RDPID)
|
||||
ASMJIT_X86_FEATURE(RDPRU)
|
||||
ASMJIT_X86_FEATURE(RDRAND)
|
||||
ASMJIT_X86_FEATURE(RDSEED)
|
||||
ASMJIT_X86_FEATURE(RDTSC)
|
||||
ASMJIT_X86_FEATURE(RDTSCP)
|
||||
ASMJIT_X86_FEATURE(RTM)
|
||||
ASMJIT_X86_FEATURE(SERIALIZE)
|
||||
ASMJIT_X86_FEATURE(SHA)
|
||||
ASMJIT_X86_FEATURE(SKINIT)
|
||||
ASMJIT_X86_FEATURE(SMAP)
|
||||
ASMJIT_X86_FEATURE(SMEP)
|
||||
ASMJIT_X86_FEATURE(SMX)
|
||||
ASMJIT_X86_FEATURE(SNP)
|
||||
ASMJIT_X86_FEATURE(SSE)
|
||||
ASMJIT_X86_FEATURE(SSE2)
|
||||
ASMJIT_X86_FEATURE(SSE3)
|
||||
@@ -267,6 +282,7 @@ public:
|
||||
ASMJIT_X86_FEATURE(SVM)
|
||||
ASMJIT_X86_FEATURE(TBM)
|
||||
ASMJIT_X86_FEATURE(TSX)
|
||||
ASMJIT_X86_FEATURE(TSXLDTRK)
|
||||
ASMJIT_X86_FEATURE(XSAVE)
|
||||
ASMJIT_X86_FEATURE(XSAVEC)
|
||||
ASMJIT_X86_FEATURE(XSAVEOPT)
|
||||
|
||||
@@ -78,6 +78,7 @@ struct RegFormatInfo_T {
|
||||
X == Reg::kTypeDReg ? 62 :
|
||||
X == Reg::kTypeSt ? 47 :
|
||||
X == Reg::kTypeBnd ? 55 :
|
||||
X == Reg::kTypeTmm ? 65 :
|
||||
X == Reg::kTypeRip ? 39 : 0,
|
||||
|
||||
kFormatIndex = X == Reg::kTypeGpbLo ? 1 :
|
||||
@@ -95,6 +96,7 @@ struct RegFormatInfo_T {
|
||||
X == Reg::kTypeDReg ? 80 :
|
||||
X == Reg::kTypeSt ? 55 :
|
||||
X == Reg::kTypeBnd ? 69 :
|
||||
X == Reg::kTypeTmm ? 89 :
|
||||
X == Reg::kTypeRip ? 43 : 0,
|
||||
|
||||
kSpecialIndex = X == Reg::kTypeGpbLo ? 96 :
|
||||
@@ -146,7 +148,9 @@ static const RegFormatInfo x86RegFormatInfo = {
|
||||
"k\0" // #53
|
||||
"bnd\0" // #55
|
||||
"cr\0" // #59
|
||||
"dr\0", // #62
|
||||
"dr\0" // #62
|
||||
"tmm\0" // #65
|
||||
,
|
||||
|
||||
// Register name entries and strings.
|
||||
{ ASMJIT_LOOKUP_TABLE_32(ASMJIT_REG_NAME_ENTRY, 0) },
|
||||
@@ -170,7 +174,8 @@ static const RegFormatInfo x86RegFormatInfo = {
|
||||
"dr%u\0" // #80
|
||||
|
||||
"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
|
||||
"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"
|
||||
"AESNI\0"
|
||||
"ALTMOVCR8\0"
|
||||
"AMX_BF16\0"
|
||||
"AMX_INT8\0"
|
||||
"AMX_TILE\0"
|
||||
"AVX\0"
|
||||
"AVX2\0"
|
||||
"AVX512_4FMAPS\0"
|
||||
@@ -257,6 +265,7 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept
|
||||
"LAHFSAHF\0"
|
||||
"LWP\0"
|
||||
"LZCNT\0"
|
||||
"MCOMMIT\0"
|
||||
"MMX\0"
|
||||
"MMX2\0"
|
||||
"MONITOR\0"
|
||||
@@ -275,16 +284,19 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept
|
||||
"PREFETCHW\0"
|
||||
"PREFETCHWT1\0"
|
||||
"RDPID\0"
|
||||
"RDPRU\0"
|
||||
"RDRAND\0"
|
||||
"RDSEED\0"
|
||||
"RDTSC\0"
|
||||
"RDTSCP\0"
|
||||
"RTM\0"
|
||||
"SERIALIZE\0"
|
||||
"SHA\0"
|
||||
"SKINIT\0"
|
||||
"SMAP\0"
|
||||
"SMEP\0"
|
||||
"SMX\0"
|
||||
"SNP\0"
|
||||
"SSE\0"
|
||||
"SSE2\0"
|
||||
"SSE3\0"
|
||||
@@ -295,6 +307,7 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept
|
||||
"SVM\0"
|
||||
"TBM\0"
|
||||
"TSX\0"
|
||||
"TSXLDTRK\0"
|
||||
"VAES\0"
|
||||
"VMX\0"
|
||||
"VPCLMULQDQ\0"
|
||||
@@ -308,13 +321,14 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept
|
||||
"<Unknown>\0";
|
||||
|
||||
static const uint16_t sFeatureIndex[] = {
|
||||
0, 5, 8, 11, 17, 24, 28, 34, 44, 48, 53, 67, 81, 93, 107, 117, 128, 138,
|
||||
149, 158, 170, 181, 193, 206, 216, 228, 248, 265, 269, 274, 283, 291, 302,
|
||||
307, 314, 319, 330, 340, 346, 353, 358, 363, 367, 372, 376, 385, 390, 398,
|
||||
404, 409, 413, 418, 427, 431, 437, 441, 446, 454, 463, 469, 479, 487, 491,
|
||||
495, 500, 508, 518, 526, 534, 541, 551, 563, 569, 576, 583, 589, 596, 600,
|
||||
604, 611, 616, 621, 625, 629, 634, 639, 646, 653, 659, 665, 669, 673, 677,
|
||||
682, 686, 697, 705, 714, 718, 724, 731, 740, 747
|
||||
0, 5, 8, 11, 17, 24, 28, 34, 44, 53, 62, 71, 75, 80, 94, 108, 120, 134, 144,
|
||||
155, 165, 176, 185, 197, 208, 220, 233, 243, 255, 275, 292, 296, 301, 310,
|
||||
318, 329, 334, 341, 346, 357, 367, 373, 380, 385, 390, 394, 399, 403, 412,
|
||||
417, 425, 431, 436, 440, 445, 454, 458, 464, 472, 476, 481, 489, 498, 504,
|
||||
514, 522, 526, 530, 535, 543, 553, 561, 569, 576, 586, 598, 604, 610, 617,
|
||||
624, 630, 637, 641, 651, 655, 662, 667, 672, 676, 680, 684, 689, 694, 701,
|
||||
708, 714, 720, 724, 728, 732, 741, 746, 750, 761, 769, 778, 782, 788, 795,
|
||||
804, 811
|
||||
};
|
||||
// @EnumStringEnd@
|
||||
|
||||
|
||||
@@ -422,6 +422,7 @@ struct Inst : public BaseInst {
|
||||
kIdLddqu, //!< Instruction 'lddqu' {SSE3}.
|
||||
kIdLdmxcsr, //!< Instruction 'ldmxcsr' {SSE}.
|
||||
kIdLds, //!< Instruction 'lds' (X86).
|
||||
kIdLdtilecfg, //!< Instruction 'ldtilecfg' {AMX_TILE} (X64).
|
||||
kIdLea, //!< Instruction 'lea'.
|
||||
kIdLeave, //!< Instruction 'leave'.
|
||||
kIdLes, //!< Instruction 'les' (X86).
|
||||
@@ -449,6 +450,7 @@ struct Inst : public BaseInst {
|
||||
kIdMaxps, //!< Instruction 'maxps' {SSE}.
|
||||
kIdMaxsd, //!< Instruction 'maxsd' {SSE2}.
|
||||
kIdMaxss, //!< Instruction 'maxss' {SSE}.
|
||||
kIdMcommit, //!< Instruction 'mcommit' {MCOMMIT}.
|
||||
kIdMfence, //!< Instruction 'mfence' {SSE2}.
|
||||
kIdMinpd, //!< Instruction 'minpd' {SSE2}.
|
||||
kIdMinps, //!< Instruction 'minps' {SSE}.
|
||||
@@ -550,6 +552,7 @@ struct Inst : public BaseInst {
|
||||
kIdPcmpistri, //!< Instruction 'pcmpistri' {SSE4_2}.
|
||||
kIdPcmpistrm, //!< Instruction 'pcmpistrm' {SSE4_2}.
|
||||
kIdPcommit, //!< Instruction 'pcommit' {PCOMMIT}.
|
||||
kIdPconfig, //!< Instruction 'pconfig' {PCONFIG}.
|
||||
kIdPdep, //!< Instruction 'pdep' {BMI2}.
|
||||
kIdPext, //!< Instruction 'pext' {BMI2}.
|
||||
kIdPextrb, //!< Instruction 'pextrb' {SSE4_1}.
|
||||
@@ -653,6 +656,7 @@ struct Inst : public BaseInst {
|
||||
kIdPslldq, //!< Instruction 'pslldq' {SSE2}.
|
||||
kIdPsllq, //!< Instruction 'psllq' {MMX|SSE2}.
|
||||
kIdPsllw, //!< Instruction 'psllw' {MMX|SSE2}.
|
||||
kIdPsmash, //!< Instruction 'psmash' {SNP} (X64).
|
||||
kIdPsrad, //!< Instruction 'psrad' {MMX|SSE2}.
|
||||
kIdPsraw, //!< Instruction 'psraw' {MMX|SSE2}.
|
||||
kIdPsrld, //!< Instruction 'psrld' {MMX|SSE2}.
|
||||
@@ -683,6 +687,7 @@ struct Inst : public BaseInst {
|
||||
kIdPushf, //!< Instruction 'pushf'.
|
||||
kIdPushfd, //!< Instruction 'pushfd' (X86).
|
||||
kIdPushfq, //!< Instruction 'pushfq' (X64).
|
||||
kIdPvalidate, //!< Instruction 'pvalidate' {SNP}.
|
||||
kIdPxor, //!< Instruction 'pxor' {MMX|SSE2}.
|
||||
kIdRcl, //!< Instruction 'rcl'.
|
||||
kIdRcpps, //!< Instruction 'rcpps' {SSE}.
|
||||
@@ -693,11 +698,14 @@ struct Inst : public BaseInst {
|
||||
kIdRdmsr, //!< Instruction 'rdmsr' {MSR}.
|
||||
kIdRdpid, //!< Instruction 'rdpid' {RDPID}.
|
||||
kIdRdpmc, //!< Instruction 'rdpmc'.
|
||||
kIdRdpru, //!< Instruction 'rdpru' {RDPRU}.
|
||||
kIdRdrand, //!< Instruction 'rdrand' {RDRAND}.
|
||||
kIdRdseed, //!< Instruction 'rdseed' {RDSEED}.
|
||||
kIdRdtsc, //!< Instruction 'rdtsc' {RDTSC}.
|
||||
kIdRdtscp, //!< Instruction 'rdtscp' {RDTSCP}.
|
||||
kIdRet, //!< Instruction 'ret'.
|
||||
kIdRmpadjust, //!< Instruction 'rmpadjust' {SNP} (X64).
|
||||
kIdRmpupdate, //!< Instruction 'rmpupdate' {SNP} (X64).
|
||||
kIdRol, //!< Instruction 'rol'.
|
||||
kIdRor, //!< Instruction 'ror'.
|
||||
kIdRorx, //!< Instruction 'rorx' {BMI2}.
|
||||
@@ -714,6 +722,7 @@ struct Inst : public BaseInst {
|
||||
kIdSarx, //!< Instruction 'sarx' {BMI2}.
|
||||
kIdSbb, //!< Instruction 'sbb'.
|
||||
kIdScas, //!< Instruction 'scas'.
|
||||
kIdSerialize, //!< Instruction 'serialize' {SERIALIZE}.
|
||||
kIdSeta, //!< Instruction 'seta'.
|
||||
kIdSetae, //!< Instruction 'setae'.
|
||||
kIdSetb, //!< Instruction 'setb'.
|
||||
@@ -778,6 +787,7 @@ struct Inst : public BaseInst {
|
||||
kIdStmxcsr, //!< Instruction 'stmxcsr' {SSE}.
|
||||
kIdStos, //!< Instruction 'stos'.
|
||||
kIdStr, //!< Instruction 'str'.
|
||||
kIdSttilecfg, //!< Instruction 'sttilecfg' {AMX_TILE} (X64).
|
||||
kIdSub, //!< Instruction 'sub'.
|
||||
kIdSubpd, //!< Instruction 'subpd' {SSE2}.
|
||||
kIdSubps, //!< Instruction 'subps' {SSE}.
|
||||
@@ -791,12 +801,25 @@ struct Inst : public BaseInst {
|
||||
kIdSysret, //!< Instruction 'sysret' (X64).
|
||||
kIdSysret64, //!< Instruction 'sysret64' (X64).
|
||||
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'.
|
||||
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}.
|
||||
kIdTzmsk, //!< Instruction 'tzmsk' {TBM}.
|
||||
kIdUcomisd, //!< Instruction 'ucomisd' {SSE2}.
|
||||
kIdUcomiss, //!< Instruction 'ucomiss' {SSE}.
|
||||
kIdUd2, //!< Instruction 'ud2'.
|
||||
kIdUmonitor, //!< Instruction 'umonitor' {WAITPKG}.
|
||||
kIdUmwait, //!< Instruction 'umwait' {WAITPKG}.
|
||||
kIdUnpckhpd, //!< Instruction 'unpckhpd' {SSE2}.
|
||||
kIdUnpckhps, //!< Instruction 'unpckhps' {SSE}.
|
||||
kIdUnpcklpd, //!< Instruction 'unpcklpd' {SSE2}.
|
||||
@@ -1119,6 +1142,8 @@ struct Inst : public BaseInst {
|
||||
kIdVmxon, //!< Instruction 'vmxon' {VMX}.
|
||||
kIdVorpd, //!< Instruction 'vorpd' {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}.
|
||||
kIdVp4dpwssds, //!< Instruction 'vp4dpwssds' {AVX512_4VNNIW}.
|
||||
kIdVpabsb, //!< Instruction 'vpabsb' {AVX|AVX2|AVX512_BW+VL}.
|
||||
@@ -1538,6 +1563,7 @@ struct Inst : public BaseInst {
|
||||
kIdXor, //!< Instruction 'xor'.
|
||||
kIdXorpd, //!< Instruction 'xorpd' {SSE2}.
|
||||
kIdXorps, //!< Instruction 'xorps' {SSE}.
|
||||
kIdXresldtrk, //!< Instruction 'xresldtrk' {TSXLDTRK}.
|
||||
kIdXrstor, //!< Instruction 'xrstor' {XSAVE}.
|
||||
kIdXrstor64, //!< Instruction 'xrstor64' {XSAVE} (X64).
|
||||
kIdXrstors, //!< Instruction 'xrstors' {XSAVES}.
|
||||
@@ -1551,6 +1577,7 @@ struct Inst : public BaseInst {
|
||||
kIdXsaves, //!< Instruction 'xsaves' {XSAVES}.
|
||||
kIdXsaves64, //!< Instruction 'xsaves64' {XSAVES} (X64).
|
||||
kIdXsetbv, //!< Instruction 'xsetbv' {XSAVE}.
|
||||
kIdXsusldtrk, //!< Instruction 'xsusldtrk' {TSXLDTRK}.
|
||||
kIdXtest, //!< Instruction 'xtest' {TSX}.
|
||||
_kIdCount
|
||||
// ${InstId:End}
|
||||
|
||||
@@ -142,6 +142,7 @@ struct X86ValidationData {
|
||||
(X == Reg::kTypeDReg ) ? InstDB::kOpDReg : \
|
||||
(X == Reg::kTypeSt ) ? InstDB::kOpSt : \
|
||||
(X == Reg::kTypeBnd ) ? InstDB::kOpBnd : \
|
||||
(X == Reg::kTypeTmm ) ? InstDB::kOpTmm : \
|
||||
(X == Reg::kTypeRip ) ? InstDB::kOpNone : InstDB::kOpNone
|
||||
static const uint32_t _x86OpFlagFromRegType[Reg::kTypeMax + 1] = { ASMJIT_LOOKUP_TABLE_32(VALUE, 0) };
|
||||
#undef VALUE
|
||||
@@ -162,6 +163,7 @@ static const uint32_t _x86OpFlagFromRegType[Reg::kTypeMax + 1] = { ASMJIT_LOOKUP
|
||||
(X == Reg::kTypeDReg ) ? 0x000000FFu : \
|
||||
(X == Reg::kTypeSt ) ? 0x000000FFu : \
|
||||
(X == Reg::kTypeBnd ) ? 0x0000000Fu : \
|
||||
(X == Reg::kTypeTmm ) ? 0x000000FFu : \
|
||||
(X == Reg::kTypeRip ) ? 0x00000001u : 0u
|
||||
|
||||
#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::kTypeSt ) ? 0x000000FFu : \
|
||||
(X == Reg::kTypeBnd ) ? 0x0000000Fu : \
|
||||
(X == Reg::kTypeTmm ) ? 0x000000FFu : \
|
||||
(X == Reg::kTypeRip ) ? 0x00000001u : 0u
|
||||
|
||||
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::RWFlagsInfoTable& rwFlags = InstDB::_rwFlagsInfoTable[tabB._rwFlagsIndex];
|
||||
|
||||
// Each RWInfo contains two indexes
|
||||
// [0] - OpCount == 2
|
||||
// [1] - OpCount != 2
|
||||
// They are used this way as there are instructions that have 2 and 3
|
||||
// operand overloads that use different semantics. So instead of adding
|
||||
// more special cases we just separated their data tables.
|
||||
const InstDB::RWInfo& instRwInfo = InstDB::rwInfo[InstDB::rwInfoIndex[instId * 2u + uint32_t(opCount != 2)]];
|
||||
|
||||
// There are two data tables, one for `opCount == 2` and the second for
|
||||
// `opCount != 2`. There are two reasons for that:
|
||||
// - There are instructions that share the same name that have both 2
|
||||
// or 3 operands, which have different RW information / semantics.
|
||||
// - There must be 2 tables otherwise the lookup index won't fit into
|
||||
// 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];
|
||||
|
||||
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).
|
||||
kOpSt = 0x00002000u, //!< Operand can be 80-bit ST register (X87).
|
||||
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.
|
||||
kOpU4 = 0x00020000u, //!< Operand can be unsigned 4-bit immediate.
|
||||
kOpI8 = 0x00040000u, //!< Operand can be signed 8-bit immediate.
|
||||
kOpU8 = 0x00080000u, //!< Operand can be unsigned 8-bit immediate.
|
||||
kOpI16 = 0x00100000u, //!< Operand can be signed 16-bit immediate.
|
||||
kOpI4 = 0x00010000u, //!< 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.
|
||||
kOpU8 = 0x00080000u, //!< Operand can be unsigned 8-bit immediate.
|
||||
kOpI16 = 0x00100000u, //!< Operand can be signed 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.
|
||||
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.
|
||||
kOpAllImm = 0x03FF0000u, //!< Operand can be any immediate.
|
||||
|
||||
@@ -129,7 +130,8 @@ enum MemFlags : uint32_t {
|
||||
kMemOpDs = 0x1000u, //!< Implicit memory operand's DS 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.
|
||||
|
||||
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.
|
||||
kFlagRepIgnored = 0x00002000u, //!< Instruction ignores REP|REPNE prefixes, but they are accepted.
|
||||
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); }
|
||||
//! Tests whether the instruction uses VSIB.
|
||||
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).
|
||||
inline bool isVex() const noexcept { return hasFlag(kFlagVex); }
|
||||
//! 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_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.
|
||||
kEncodingX86R32_EDX_EAX, //!< X86 [R32] followed by implicit EDX and EAX.
|
||||
kEncodingX86Rm, //!< X86 [RM] (doesn't handle single-byte size).
|
||||
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).
|
||||
@@ -132,6 +134,7 @@ enum EncodingId : uint32_t {
|
||||
kEncodingExtInsertq, //!< EXT insrq (SSE4A).
|
||||
kEncodingExt3dNow, //!< EXT [RMI] (3DNOW specific).
|
||||
kEncodingVexOp, //!< VEX [OP].
|
||||
kEncodingVexOpMod, //!< VEX [OP] with MODR/M.
|
||||
kEncodingVexKmov, //!< VEX [RM|MR] (used by kmov[b|w|d|q]).
|
||||
kEncodingVexR_Wx, //!< VEX|EVEX [R] (propagatex VEX.W if GPQ used).
|
||||
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_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_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].
|
||||
@@ -187,6 +191,11 @@ enum EncodingId : uint32_t {
|
||||
kEncodingVexMovssMovsd, //!< VEX|EVEX vmovss, vmovsd.
|
||||
kEncodingFma4, //!< FMA4 [R, R, R/M, R/M].
|
||||
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.
|
||||
};
|
||||
|
||||
@@ -288,8 +297,10 @@ struct RWFlagsInfoTable {
|
||||
uint32_t writeFlags;
|
||||
};
|
||||
|
||||
extern const uint8_t rwInfoIndex[Inst::_kIdCount * 2];
|
||||
extern const RWInfo rwInfo[];
|
||||
extern const uint8_t rwInfoIndexA[Inst::_kIdCount];
|
||||
extern const uint8_t rwInfoIndexB[Inst::_kIdCount];
|
||||
extern const RWInfo rwInfoA[];
|
||||
extern const RWInfo rwInfoB[];
|
||||
extern const RWInfoOp rwInfoOp[];
|
||||
extern const RWInfoRm rwInfoRm[];
|
||||
extern const RWFlagsInfoTable _rwFlagsInfoTable[];
|
||||
|
||||
@@ -337,14 +337,17 @@ struct Opcode {
|
||||
k000F3A = kPP_00 | kMM_0F3A, // '0F3A'
|
||||
k660000 = kPP_66 | kMM_00, // '66'
|
||||
k660F00 = kPP_66 | kMM_0F, // '660F'
|
||||
k660F01 = kPP_66 | kMM_0F01, // '660F01'
|
||||
k660F38 = kPP_66 | kMM_0F38, // '660F38'
|
||||
k660F3A = kPP_66 | kMM_0F3A, // '660F3A'
|
||||
kF20000 = kPP_F2 | kMM_00, // 'F2'
|
||||
kF20F00 = kPP_F2 | kMM_0F, // 'F20F'
|
||||
kF20F01 = kPP_F2 | kMM_0F01, // 'F20F01'
|
||||
kF20F38 = kPP_F2 | kMM_0F38, // 'F20F38'
|
||||
kF20F3A = kPP_F2 | kMM_0F3A, // 'F20F3A'
|
||||
kF30000 = kPP_F3 | kMM_00, // 'F3'
|
||||
kF30F00 = kPP_F3 | kMM_0F, // 'F30F'
|
||||
kF30F01 = kPP_F3 | kMM_0F01, // 'F30F01'
|
||||
kF30F38 = kPP_F3 | kMM_0F38, // 'F30F38'
|
||||
kF30F3A = kPP_F3 | kMM_0F3A, // 'F30F3A'
|
||||
kFPU_00 = kPP_00 | kMM_00, // '__' (FPU)
|
||||
|
||||
@@ -108,6 +108,7 @@ class CReg;
|
||||
class DReg;
|
||||
class St;
|
||||
class Bnd;
|
||||
class Tmm;
|
||||
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(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(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
|
||||
|
||||
//! Register (X86).
|
||||
@@ -152,41 +154,78 @@ public:
|
||||
|
||||
//! Register type.
|
||||
enum RegType : uint32_t {
|
||||
kTypeNone = BaseReg::kTypeNone, //!< No register type or invalid register.
|
||||
kTypeGpbLo = BaseReg::kTypeGp8Lo, //!< Low GPB register (AL, BL, CL, DL, ...).
|
||||
kTypeGpbHi = BaseReg::kTypeGp8Hi, //!< High GPB register (AH, BH, CH, DH only).
|
||||
kTypeGpw = BaseReg::kTypeGp16, //!< GPW register.
|
||||
kTypeGpd = BaseReg::kTypeGp32, //!< GPD register.
|
||||
kTypeGpq = BaseReg::kTypeGp64, //!< GPQ register (64-bit).
|
||||
kTypeXmm = BaseReg::kTypeVec128, //!< XMM register (SSE+).
|
||||
kTypeYmm = BaseReg::kTypeVec256, //!< YMM register (AVX+).
|
||||
kTypeZmm = BaseReg::kTypeVec512, //!< ZMM register (AVX512+).
|
||||
kTypeMm = BaseReg::kTypeOther0, //!< MMX register.
|
||||
kTypeKReg = BaseReg::kTypeOther1, //!< K register (AVX512+).
|
||||
kTypeSReg = BaseReg::kTypeCustom+0, //!< Segment register (None, ES, CS, SS, DS, FS, GS).
|
||||
kTypeCReg = BaseReg::kTypeCustom+1, //!< Control register (CR).
|
||||
kTypeDReg = BaseReg::kTypeCustom+2, //!< Debug register (DR).
|
||||
kTypeSt = BaseReg::kTypeCustom+3, //!< FPU (x87) register.
|
||||
kTypeBnd = BaseReg::kTypeCustom+4, //!< Bound register (BND).
|
||||
kTypeRip = BaseReg::kTypeIP, //!< Instruction pointer (EIP, RIP).
|
||||
kTypeCount = BaseReg::kTypeCustom+5 //!< Count of register types.
|
||||
//! No register type or invalid register.
|
||||
kTypeNone = BaseReg::kTypeNone,
|
||||
|
||||
//! Low GPB register (AL, BL, CL, DL, ...).
|
||||
kTypeGpbLo = BaseReg::kTypeGp8Lo,
|
||||
//! High GPB register (AH, BH, CH, DH only).
|
||||
kTypeGpbHi = BaseReg::kTypeGp8Hi,
|
||||
//! GPW register.
|
||||
kTypeGpw = BaseReg::kTypeGp16,
|
||||
//! GPD register.
|
||||
kTypeGpd = BaseReg::kTypeGp32,
|
||||
//! GPQ register (64-bit).
|
||||
kTypeGpq = BaseReg::kTypeGp64,
|
||||
//! XMM register (SSE+).
|
||||
kTypeXmm = BaseReg::kTypeVec128,
|
||||
//! YMM register (AVX+).
|
||||
kTypeYmm = BaseReg::kTypeVec256,
|
||||
//! 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.
|
||||
enum RegGroup : uint32_t {
|
||||
kGroupGp = BaseReg::kGroupGp, //!< GP register group or none (universal).
|
||||
kGroupVec = BaseReg::kGroupVec, //!< XMM|YMM|ZMM register group (universal).
|
||||
kGroupMm = BaseReg::kGroupOther0, //!< MMX register group (legacy).
|
||||
kGroupKReg = BaseReg::kGroupOther1, //!< K register group.
|
||||
//! GP register group or none (universal).
|
||||
kGroupGp = BaseReg::kGroupGp,
|
||||
//! XMM|YMM|ZMM register group (universal).
|
||||
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:
|
||||
kGroupSReg = BaseReg::kGroupVirt+0, //!< Segment register group.
|
||||
kGroupCReg = BaseReg::kGroupVirt+1, //!< Control register group.
|
||||
kGroupDReg = BaseReg::kGroupVirt+2, //!< Debug register group.
|
||||
kGroupSt = BaseReg::kGroupVirt+3, //!< FPU register group.
|
||||
kGroupBnd = BaseReg::kGroupVirt+4, //!< Bound register group.
|
||||
kGroupRip = BaseReg::kGroupVirt+5, //!< Instrucion pointer (IP).
|
||||
kGroupCount //!< Count of all register groups.
|
||||
// These are not managed by Compiler nor used by Func-API:
|
||||
|
||||
//! Segment register group.
|
||||
kGroupSReg = BaseReg::kGroupVirt+0,
|
||||
//! Control register group.
|
||||
kGroupCReg = BaseReg::kGroupVirt+1,
|
||||
//! Debug register group.
|
||||
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).
|
||||
@@ -221,6 +260,8 @@ public:
|
||||
constexpr bool isSt() const noexcept { return hasSignature(RegTraits<kTypeSt>::kSignature); }
|
||||
//! Tests whether the register is a bound register.
|
||||
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.
|
||||
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 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 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 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 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 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); }
|
||||
};
|
||||
|
||||
@@ -368,19 +411,26 @@ class SReg : public Reg {
|
||||
|
||||
//! X86 segment id.
|
||||
enum Id : uint32_t {
|
||||
kIdNone = 0, //!< No segment (default).
|
||||
kIdEs = 1, //!< ES segment.
|
||||
kIdCs = 2, //!< CS segment.
|
||||
kIdSs = 3, //!< SS segment.
|
||||
kIdDs = 4, //!< DS segment.
|
||||
kIdFs = 5, //!< FS segment.
|
||||
kIdGs = 6, //!< GS segment.
|
||||
//! No segment (default).
|
||||
kIdNone = 0,
|
||||
//! ES segment.
|
||||
kIdEs = 1,
|
||||
//! CS segment.
|
||||
kIdCs = 2,
|
||||
//! 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.
|
||||
//! 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
|
||||
//! there is no segment register specified.
|
||||
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>) };
|
||||
//! 128-bit BND register (BND+).
|
||||
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).
|
||||
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); }
|
||||
//! Creates a 128-bit bound register operand.
|
||||
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 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 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);
|
||||
|
||||
#ifndef _DOXYGEN
|
||||
|
||||
@@ -221,6 +221,9 @@ class GenUtils {
|
||||
}
|
||||
}
|
||||
|
||||
if (dbInst.attributes.Tsib)
|
||||
f.Tsib = true;
|
||||
|
||||
if (dbInst.vsibReg)
|
||||
f.Vsib = true;
|
||||
|
||||
@@ -509,7 +512,9 @@ class X86TableGen extends core.TableGen {
|
||||
String(inst.encoding ).padEnd(19) + ", " +
|
||||
String(inst.opcode0 ).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) + "),\n";
|
||||
}
|
||||
@@ -930,6 +935,7 @@ const OpToAsmJitOp = {
|
||||
"dreg" : "F(DReg)",
|
||||
"st" : "F(St)",
|
||||
"bnd" : "F(Bnd)",
|
||||
"tmm" : "F(Tmm)",
|
||||
|
||||
"mem" : "F(Mem)",
|
||||
"vm" : "F(Vm)",
|
||||
@@ -1096,7 +1102,8 @@ class OSignature {
|
||||
case "mm" :
|
||||
case "xmm" :
|
||||
case "ymm" :
|
||||
case "zmm" : mFlags[k] = true; break;
|
||||
case "zmm" :
|
||||
case "tmm" : mFlags[k] = true; break;
|
||||
|
||||
case "m8" :
|
||||
case "m16" :
|
||||
@@ -1108,8 +1115,9 @@ class OSignature {
|
||||
case "m256" :
|
||||
case "m512" :
|
||||
case "m1024" : mFlags.mem = true; mMemFlags[k] = true; break;
|
||||
case "mib" : mFlags.mem = true; mMemFlags.mib = true; break;
|
||||
case "mem" : mFlags.mem = true; mMemFlags.mAny = true; break;
|
||||
case "mib" : mFlags.mem = true; mMemFlags.mib = 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 "memDS" : mFlags.mem = true; mMemFlags.memDS = true; break;
|
||||
@@ -1814,8 +1822,11 @@ class InstRWInfoTable extends core.Task {
|
||||
constructor() {
|
||||
super("InstRWInfoTable");
|
||||
|
||||
this.rwInfoIndex = [];
|
||||
this.rwInfoTable = new IndexedArray();
|
||||
this.rwInfoIndexA = [];
|
||||
this.rwInfoIndexB = [];
|
||||
this.rwInfoTableA = new IndexedArray();
|
||||
this.rwInfoTableB = new IndexedArray();
|
||||
|
||||
this.rmInfoTable = 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); })))
|
||||
);
|
||||
|
||||
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 = "";
|
||||
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 += "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 += "const InstDB::RWInfoOp InstDB::rwInfoOp[] = {\n" + StringUtils.format(this.opInfoTable, kIndent, true) + "\n};\n";
|
||||
s += "\n";
|
||||
s += "const InstDB::RWInfoRm InstDB::rwInfoRm[] = {\n" + StringUtils.format(this.rmInfoTable, kIndent, true) + "\n};\n";
|
||||
|
||||
const size = this.rwInfoIndex.length +
|
||||
this.rwInfoTable.length * 8 +
|
||||
const size = this.rwInfoIndexA.length +
|
||||
this.rwInfoIndexB.length +
|
||||
this.rwInfoTableA.length * 8 +
|
||||
this.rwInfoTableB.length * 8 +
|
||||
this.rmInfoTable.length * 4 +
|
||||
this.opInfoTable.length * 24;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user