-
-
Save kobalicek/6a11464e2c6777f1c87d44f779e82b7d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <asmjit/x86.h> | |
#include <assert.h> | |
#include <stdio.h> | |
using namespace asmjit; | |
class InstSignatureIterator { | |
public: | |
typedef asmjit::x86::InstDB::InstSignature InstSignature; | |
typedef asmjit::x86::InstDB::OpSignature OpSignature; | |
const InstSignature* _instSignature; | |
const OpSignature* _opSigArray[asmjit::Globals::kMaxOpCount]; | |
x86::InstDB::OpFlags _opMaskArray[asmjit::Globals::kMaxOpCount]; | |
uint32_t _opCount; | |
x86::InstDB::OpFlags _filter; | |
bool _isValid; | |
static constexpr uint32_t kMaxOpCount = Globals::kMaxOpCount; | |
static constexpr x86::InstDB::OpFlags kDefaultFilter = | |
x86::InstDB::OpFlags::kRegMask | | |
x86::InstDB::OpFlags::kMemMask | | |
x86::InstDB::OpFlags::kVmMask | | |
x86::InstDB::OpFlags::kImmMask | | |
x86::InstDB::OpFlags::kRelMask ; | |
inline InstSignatureIterator() { reset(); } | |
inline InstSignatureIterator(const InstSignature* instSignature, x86::InstDB::OpFlags filter = kDefaultFilter) { init(instSignature, filter); } | |
inline InstSignatureIterator(const InstSignatureIterator& other) { init(other); } | |
inline void reset() { ::memset(this, 0, sizeof(*this)); } | |
inline void init(const InstSignatureIterator& other) { ::memcpy(this, &other, sizeof(*this)); } | |
void init(const InstSignature* instSignature, x86::InstDB::OpFlags filter = kDefaultFilter) { | |
const OpSignature* opSigArray = asmjit::x86::InstDB::_opSignatureTable; | |
uint32_t opCount = instSignature->opCount(); | |
_instSignature = instSignature; | |
_opCount = opCount; | |
_filter = filter; | |
uint32_t i; | |
x86::InstDB::OpFlags flags = x86::InstDB::OpFlags::kNone; | |
for (i = 0; i < opCount; i++) { | |
const OpSignature& opSig = instSignature->opSignature(i); | |
flags = opSig.flags() & _filter; | |
if (flags == x86::InstDB::OpFlags::kNone) | |
break; | |
_opSigArray[i] = &opSig; | |
_opMaskArray[i] = x86::InstDB::OpFlags(asmjit::Support::blsi(uint64_t(flags))); | |
} | |
while (i < kMaxOpCount) { | |
_opSigArray[i] = &opSigArray[0]; | |
_opMaskArray[i] = x86::InstDB::OpFlags::kNone; | |
i++; | |
} | |
_isValid = opCount == 0 || flags != x86::InstDB::OpFlags::kNone; | |
} | |
inline bool isValid() const { return _isValid; } | |
inline uint32_t opCount() const { return _opCount; } | |
inline const x86::InstDB::OpFlags* opMaskArray() const { return _opMaskArray; } | |
inline const OpSignature* const* opSigArray() const { return _opSigArray; } | |
inline x86::InstDB::OpFlags opMask(uint32_t i) const { return _opMaskArray[i]; } | |
inline const OpSignature* opSig(uint32_t i) const { return _opSigArray[i]; } | |
bool next() { | |
uint32_t i = _opCount - 1u; | |
for (;;) { | |
if (i == 0xFFFFFFFFu) { | |
_isValid = false; | |
return false; | |
} | |
// Iterate over OpFlags. | |
x86::InstDB::OpFlags prevBit = _opMaskArray[i]; | |
x86::InstDB::OpFlags allFlags = _opSigArray[i]->flags() & _filter; | |
x86::InstDB::OpFlags bitsToClear = (x86::InstDB::OpFlags)(uint64_t(prevBit) | (uint64_t(prevBit) - 1u)); | |
x86::InstDB::OpFlags remainingBits = allFlags & ~bitsToClear; | |
if (remainingBits != x86::InstDB::OpFlags::kNone) { | |
_opMaskArray[i] = (x86::InstDB::OpFlags)asmjit::Support::blsi(uint64_t(remainingBits)); | |
return true; | |
} | |
else { | |
_opMaskArray[i--] = (x86::InstDB::OpFlags)asmjit::Support::blsi(uint64_t(allFlags)); | |
} | |
} | |
} | |
}; | |
static void listISA(Arch arch) { | |
printf("=== Listing ISA %s ===", arch == Arch::kX86 ? "X86" : "X64"); | |
x86::InstDB::Mode mode = x86::InstDB::modeFromArch(arch); | |
x86::InstDB::OpFlags opFilter = | |
x86::InstDB::OpFlags::kRegMask | | |
x86::InstDB::OpFlags::kMemMask | | |
x86::InstDB::OpFlags::kVmMask | | |
x86::InstDB::OpFlags::kImmMask | | |
x86::InstDB::OpFlags::kRelMask ; | |
if (arch == Arch::kX86) | |
opFilter &= ~x86::InstDB::OpFlags::kRegGpq; | |
for (InstId instId = 1; instId < x86::Inst::_kIdCount; instId++) { | |
const x86::InstDB::InstInfo& instInfo = x86::InstDB::infoById(instId); | |
const x86::InstDB::CommonInfo& commonInfo = instInfo.commonInfo(); | |
const x86::InstDB::InstSignature* instSignature = commonInfo.signatureData(); | |
const x86::InstDB::InstSignature* iEnd = commonInfo.signatureEnd(); | |
// Iterate over all signatures and build the instruction we want to test. | |
for (; instSignature != iEnd; instSignature++) { | |
if (!instSignature->supportsMode(mode)) | |
continue; | |
InstSignatureIterator it(instSignature, opFilter); | |
while (it.isValid()) { | |
String s; | |
InstAPI::instIdToString(arch, instId, s); | |
s.append(' '); | |
for (uint32_t opIndex = 0; opIndex < it.opCount(); opIndex++) { | |
const x86::InstDB::OpSignature* opSig = it.opSig(opIndex); | |
if (opIndex != 0) | |
s.append(", "); | |
// NOTE: The iterator iterates over all combinations, always keeping only one bit in the mask. | |
x86::InstDB::OpFlags flag = it.opMask(opIndex); | |
switch (flag) { | |
case x86::InstDB::OpFlags::kRegBnd: s.append("bnd"); break; | |
case x86::InstDB::OpFlags::kRegCReg: s.append("c"); break; | |
case x86::InstDB::OpFlags::kRegDReg: s.append("d"); break; | |
case x86::InstDB::OpFlags::kRegGpbLo: s.append("gpbLo"); break; | |
case x86::InstDB::OpFlags::kRegGpbHi: s.append("gpbHi"); break; | |
case x86::InstDB::OpFlags::kRegGpw: s.append("gpw"); break; | |
case x86::InstDB::OpFlags::kRegGpd: s.append("gpd"); break; | |
case x86::InstDB::OpFlags::kRegGpq: s.append("gpq"); break; | |
case x86::InstDB::OpFlags::kRegKReg: s.append("k"); break; | |
case x86::InstDB::OpFlags::kRegMm: s.append("mm"); break; | |
case x86::InstDB::OpFlags::kRegXmm: s.append("xmm"); break; | |
case x86::InstDB::OpFlags::kRegYmm: s.append("ymm"); break; | |
case x86::InstDB::OpFlags::kRegZmm: s.append("zmm"); break; | |
case x86::InstDB::OpFlags::kRegSReg: s.append("s"); break; | |
case x86::InstDB::OpFlags::kRegSt: s.append("st"); break; | |
case x86::InstDB::OpFlags::kMem8: s.append("m8"); break; | |
case x86::InstDB::OpFlags::kMem16: s.append("m16"); break; | |
case x86::InstDB::OpFlags::kMem32: s.append("m32"); break; | |
case x86::InstDB::OpFlags::kMem48: s.append("m48"); break; | |
case x86::InstDB::OpFlags::kMem64: s.append("m64"); break; | |
case x86::InstDB::OpFlags::kMem80: s.append("m80"); break; | |
case x86::InstDB::OpFlags::kMem128: s.append("m128"); break; | |
case x86::InstDB::OpFlags::kMem256: s.append("m256"); break; | |
case x86::InstDB::OpFlags::kMem512: s.append("m512"); break; | |
case x86::InstDB::OpFlags::kMem1024: s.append("m1024"); break; | |
case x86::InstDB::OpFlags::kMemUnspecified: s.append("m"); break; | |
case x86::InstDB::OpFlags::kVm32x: s.append("vm32x"); break; | |
case x86::InstDB::OpFlags::kVm32y: s.append("vm32y"); break; | |
case x86::InstDB::OpFlags::kVm32z: s.append("vm32z"); break; | |
case x86::InstDB::OpFlags::kVm64x: s.append("vm64x"); break; | |
case x86::InstDB::OpFlags::kVm64y: s.append("vm64y"); break; | |
case x86::InstDB::OpFlags::kVm64z: s.append("vm64z"); break; | |
case x86::InstDB::OpFlags::kImmI4: s.append("i4"); break; | |
case x86::InstDB::OpFlags::kImmI8: s.append("i8"); break; | |
case x86::InstDB::OpFlags::kImmI16: s.append("i16"); break; | |
case x86::InstDB::OpFlags::kImmI32: s.append("i32"); break; | |
case x86::InstDB::OpFlags::kImmI64: s.append("i64"); break; | |
case x86::InstDB::OpFlags::kImmU4: s.append("u4"); break; | |
case x86::InstDB::OpFlags::kImmU8: s.append("u8"); break; | |
case x86::InstDB::OpFlags::kImmU16: s.append("u16"); break; | |
case x86::InstDB::OpFlags::kImmU32: s.append("u32"); break; | |
case x86::InstDB::OpFlags::kImmU64: s.append("u64"); break; | |
case x86::InstDB::OpFlags::kRel8: s.append("rel8"); break; | |
case x86::InstDB::OpFlags::kRel32: s.append("rel32"); break; | |
default: s.append("<Unknown>"); break; | |
} | |
} | |
printf("%s\n", s.data()); | |
it.next(); | |
} | |
} | |
} | |
} | |
int main(int argc, char* argv[]) { | |
listISA(Arch::kX64); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment