mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 12:34:35 +03:00
Fixed encoding of 'CRC32 r64, r8/m8' instruction
Fixed encoding of 'POPCNT|TZCNT|LZCNT r16, r16/m16' instruction Fixed encoding of EVEX instructions that don't provide VEX prefix equivalent Added 'LOCK MOV CR8' extension used by AMD processors in 32-bit mode and 'ALTMOVCR8' CPU feature Renamed some CPU features to respect their names used in X86/X64 architecture manuals Added validation of immediate operands (correct size, correct sign/zero extension) Added validation of explicit/implicit size of memory operands Added validation of LOCK/REP/REPNZ prefixes to x86 validator Reorganized some X86 instruction tables, removed family specific tables, introduced OperationData Improved instruction tables generator to automatically generate instruction flags Regenerated all instruction tables to respect the current state of 'asmdb.x86data'
This commit is contained in:
@@ -196,8 +196,6 @@ cxx_add_source(asmjit ASMJIT_SRC asmjit/x86
|
|||||||
x86operand.h
|
x86operand.h
|
||||||
x86regalloc.cpp
|
x86regalloc.cpp
|
||||||
x86regalloc_p.h
|
x86regalloc_p.h
|
||||||
x86ssetoavxpass.cpp
|
|
||||||
x86ssetoavxpass_p.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
|
|||||||
@@ -393,6 +393,7 @@ ASMJIT_FAVOR_SIZE static void x86DetectCpuInfo(CpuInfo* cpuInfo) noexcept {
|
|||||||
XGetBVResult xcr0 = { 0, 0 };
|
XGetBVResult xcr0 = { 0, 0 };
|
||||||
|
|
||||||
cpuInfo->_archInfo.init(ArchInfo::kTypeHost);
|
cpuInfo->_archInfo.init(ArchInfo::kTypeHost);
|
||||||
|
cpuInfo->addFeature(CpuInfo::kX86FeatureI486);
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// [CPUID EAX=0x0]
|
// [CPUID EAX=0x0]
|
||||||
@@ -442,9 +443,10 @@ ASMJIT_FAVOR_SIZE static void x86DetectCpuInfo(CpuInfo* cpuInfo) noexcept {
|
|||||||
if (regs.ecx & 0x00800000U) cpuInfo->addFeature(CpuInfo::kX86FeaturePOPCNT);
|
if (regs.ecx & 0x00800000U) cpuInfo->addFeature(CpuInfo::kX86FeaturePOPCNT);
|
||||||
if (regs.ecx & 0x02000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureAESNI);
|
if (regs.ecx & 0x02000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureAESNI);
|
||||||
if (regs.ecx & 0x04000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureXSAVE);
|
if (regs.ecx & 0x04000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureXSAVE);
|
||||||
if (regs.ecx & 0x08000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureXSAVE_OS);
|
if (regs.ecx & 0x08000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureOSXSAVE);
|
||||||
if (regs.ecx & 0x40000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureRDRAND);
|
if (regs.ecx & 0x40000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureRDRAND);
|
||||||
if (regs.edx & 0x00000010U) cpuInfo->addFeature(CpuInfo::kX86FeatureRDTSC);
|
if (regs.edx & 0x00000010U) cpuInfo->addFeature(CpuInfo::kX86FeatureRDTSC);
|
||||||
|
if (regs.edx & 0x00000020U) cpuInfo->addFeature(CpuInfo::kX86FeatureMSR);
|
||||||
if (regs.edx & 0x00000100U) cpuInfo->addFeature(CpuInfo::kX86FeatureCMPXCHG8B);
|
if (regs.edx & 0x00000100U) cpuInfo->addFeature(CpuInfo::kX86FeatureCMPXCHG8B);
|
||||||
if (regs.edx & 0x00008000U) cpuInfo->addFeature(CpuInfo::kX86FeatureCMOV);
|
if (regs.edx & 0x00008000U) cpuInfo->addFeature(CpuInfo::kX86FeatureCMOV);
|
||||||
if (regs.edx & 0x00080000U) cpuInfo->addFeature(CpuInfo::kX86FeatureCLFLUSH);
|
if (regs.edx & 0x00080000U) cpuInfo->addFeature(CpuInfo::kX86FeatureCLFLUSH);
|
||||||
@@ -468,14 +470,14 @@ ASMJIT_FAVOR_SIZE static void x86DetectCpuInfo(CpuInfo* cpuInfo) noexcept {
|
|||||||
if ((xcr0.eax & 0x00000006U) == 0x00000006U) {
|
if ((xcr0.eax & 0x00000006U) == 0x00000006U) {
|
||||||
cpuInfo->addFeature(CpuInfo::kX86FeatureAVX);
|
cpuInfo->addFeature(CpuInfo::kX86FeatureAVX);
|
||||||
|
|
||||||
if (regs.ecx & 0x00004000U) cpuInfo->addFeature(CpuInfo::kX86FeatureFMA3);
|
if (regs.ecx & 0x00004000U) cpuInfo->addFeature(CpuInfo::kX86FeatureFMA);
|
||||||
if (regs.ecx & 0x20000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureF16C);
|
if (regs.ecx & 0x20000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureF16C);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// [CPUID EAX=0x7 ECX=0x0]
|
// [CPUID EAX=0x7]
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
// Detect new features if the processor supports CPUID-07.
|
// Detect new features if the processor supports CPUID-07.
|
||||||
@@ -496,7 +498,7 @@ ASMJIT_FAVOR_SIZE static void x86DetectCpuInfo(CpuInfo* cpuInfo) noexcept {
|
|||||||
if (regs.ebx & 0x00080000U) cpuInfo->addFeature(CpuInfo::kX86FeatureADX);
|
if (regs.ebx & 0x00080000U) cpuInfo->addFeature(CpuInfo::kX86FeatureADX);
|
||||||
if (regs.ebx & 0x00100000U) cpuInfo->addFeature(CpuInfo::kX86FeatureSMAP);
|
if (regs.ebx & 0x00100000U) cpuInfo->addFeature(CpuInfo::kX86FeatureSMAP);
|
||||||
if (regs.ebx & 0x00400000U) cpuInfo->addFeature(CpuInfo::kX86FeaturePCOMMIT);
|
if (regs.ebx & 0x00400000U) cpuInfo->addFeature(CpuInfo::kX86FeaturePCOMMIT);
|
||||||
if (regs.ebx & 0x00800000U) cpuInfo->addFeature(CpuInfo::kX86FeatureCLFLUSH_OPT);
|
if (regs.ebx & 0x00800000U) cpuInfo->addFeature(CpuInfo::kX86FeatureCLFLUSHOPT);
|
||||||
if (regs.ebx & 0x01000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureCLWB);
|
if (regs.ebx & 0x01000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureCLWB);
|
||||||
if (regs.ebx & 0x20000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureSHA);
|
if (regs.ebx & 0x20000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureSHA);
|
||||||
if (regs.ecx & 0x00000001U) cpuInfo->addFeature(CpuInfo::kX86FeaturePREFETCHWT1);
|
if (regs.ecx & 0x00000001U) cpuInfo->addFeature(CpuInfo::kX86FeaturePREFETCHWT1);
|
||||||
@@ -531,16 +533,18 @@ ASMJIT_FAVOR_SIZE static void x86DetectCpuInfo(CpuInfo* cpuInfo) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// [CPUID EAX=0xD, ECX=0x0]
|
// [CPUID EAX=0xD]
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
if (maxId >= 0xD && maybeMPX) {
|
if (maxId >= 0xD) {
|
||||||
x86CallCpuId(®s, 0xD);
|
x86CallCpuId(®s, 0xD, 0);
|
||||||
|
|
||||||
// Both CPUID result and XCR0 has to be enabled to have support for MPX.
|
// Both CPUID result and XCR0 has to be enabled to have support for MPX.
|
||||||
if (((regs.eax & xcr0.eax) & 0x00000018U) == 0x00000018U) {
|
if (((regs.eax & xcr0.eax) & 0x00000018U) == 0x00000018U && maybeMPX)
|
||||||
cpuInfo->addFeature(CpuInfo::kX86FeatureMPX);
|
cpuInfo->addFeature(CpuInfo::kX86FeatureMPX);
|
||||||
}
|
|
||||||
|
x86CallCpuId(®s, 0xD, 1);
|
||||||
|
if (regs.eax & 0x00000001U) cpuInfo->addFeature(CpuInfo::kX86FeatureXSAVEOPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -563,14 +567,14 @@ ASMJIT_FAVOR_SIZE static void x86DetectCpuInfo(CpuInfo* cpuInfo) noexcept {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x80000001U:
|
case 0x80000001U:
|
||||||
if (regs.ecx & 0x00000001U) cpuInfo->addFeature(CpuInfo::kX86FeatureLAHF_SAHF);
|
if (regs.ecx & 0x00000001U) cpuInfo->addFeature(CpuInfo::kX86FeatureLAHFSAHF);
|
||||||
if (regs.ecx & 0x00000020U) cpuInfo->addFeature(CpuInfo::kX86FeatureLZCNT);
|
if (regs.ecx & 0x00000020U) cpuInfo->addFeature(CpuInfo::kX86FeatureLZCNT);
|
||||||
if (regs.ecx & 0x00000040U) cpuInfo->addFeature(CpuInfo::kX86FeatureSSE4A);
|
if (regs.ecx & 0x00000040U) cpuInfo->addFeature(CpuInfo::kX86FeatureSSE4A);
|
||||||
if (regs.ecx & 0x00000080U) cpuInfo->addFeature(CpuInfo::kX86FeatureMSSE);
|
if (regs.ecx & 0x00000080U) cpuInfo->addFeature(CpuInfo::kX86FeatureMSSE);
|
||||||
if (regs.ecx & 0x00000100U) cpuInfo->addFeature(CpuInfo::kX86FeaturePREFETCH);
|
if (regs.ecx & 0x00000100U) cpuInfo->addFeature(CpuInfo::kX86FeaturePREFETCHW);
|
||||||
if (regs.ecx & 0x00200000U) cpuInfo->addFeature(CpuInfo::kX86FeatureTBM);
|
if (regs.ecx & 0x00200000U) cpuInfo->addFeature(CpuInfo::kX86FeatureTBM);
|
||||||
if (regs.edx & 0x00100000U) cpuInfo->addFeature(CpuInfo::kX86FeatureNX);
|
if (regs.edx & 0x00100000U) cpuInfo->addFeature(CpuInfo::kX86FeatureNX);
|
||||||
if (regs.edx & 0x00200000U) cpuInfo->addFeature(CpuInfo::kX86FeatureFXSR_OPT);
|
if (regs.edx & 0x00200000U) cpuInfo->addFeature(CpuInfo::kX86FeatureFXSROPT);
|
||||||
if (regs.edx & 0x00400000U) cpuInfo->addFeature(CpuInfo::kX86FeatureMMX2);
|
if (regs.edx & 0x00400000U) cpuInfo->addFeature(CpuInfo::kX86FeatureMMX2);
|
||||||
if (regs.edx & 0x08000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureRDTSCP);
|
if (regs.edx & 0x08000000U) cpuInfo->addFeature(CpuInfo::kX86FeatureRDTSCP);
|
||||||
if (regs.edx & 0x40000000U) cpuInfo->addFeature(CpuInfo::kX86Feature3DNOW2)
|
if (regs.edx & 0x40000000U) cpuInfo->addFeature(CpuInfo::kX86Feature3DNOW2)
|
||||||
@@ -581,6 +585,11 @@ ASMJIT_FAVOR_SIZE static void x86DetectCpuInfo(CpuInfo* cpuInfo) noexcept {
|
|||||||
if (regs.ecx & 0x00000800U) cpuInfo->addFeature(CpuInfo::kX86FeatureXOP);
|
if (regs.ecx & 0x00000800U) cpuInfo->addFeature(CpuInfo::kX86FeatureXOP);
|
||||||
if (regs.ecx & 0x00010000U) cpuInfo->addFeature(CpuInfo::kX86FeatureFMA4);
|
if (regs.ecx & 0x00010000U) cpuInfo->addFeature(CpuInfo::kX86FeatureFMA4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These seem to be only supported by AMD.
|
||||||
|
if (cpuInfo->getVendorId() == CpuInfo::kVendorAMD) {
|
||||||
|
if (regs.ecx & 0x00000010U) cpuInfo->addFeature(CpuInfo::kX86FeatureALTMOVCR8);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x80000002U:
|
case 0x80000002U:
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ public:
|
|||||||
|
|
||||||
//! ARM/ARM64 CPU features.
|
//! ARM/ARM64 CPU features.
|
||||||
ASMJIT_ENUM(ArmFeatures) {
|
ASMJIT_ENUM(ArmFeatures) {
|
||||||
kArmFeatureV6, //!< ARMv6 instruction set.
|
kArmFeatureV6 = 1, //!< ARMv6 instruction set.
|
||||||
kArmFeatureV7, //!< ARMv7 instruction set.
|
kArmFeatureV7, //!< ARMv7 instruction set.
|
||||||
kArmFeatureV8, //!< ARMv8 instruction set.
|
kArmFeatureV8, //!< ARMv8 instruction set.
|
||||||
kArmFeatureTHUMB, //!< CPU provides THUMB v1 instruction set (THUMB mode).
|
kArmFeatureTHUMB, //!< CPU provides THUMB v1 instruction set (THUMB mode).
|
||||||
@@ -61,27 +61,31 @@ public:
|
|||||||
|
|
||||||
//! X86/X64 CPU features.
|
//! X86/X64 CPU features.
|
||||||
ASMJIT_ENUM(X86Features) {
|
ASMJIT_ENUM(X86Features) {
|
||||||
kX86FeatureNX = 0, //!< CPU has Not-Execute-Bit.
|
kX86FeatureI486 = 1, //!< CPU is at least I486.
|
||||||
|
kX86FeatureNX, //!< CPU has Not-Execute-Bit.
|
||||||
kX86FeatureMT, //!< CPU has multi-threading.
|
kX86FeatureMT, //!< CPU has multi-threading.
|
||||||
kX86FeatureRDTSC, //!< CPU has RDTSC.
|
kX86FeatureALTMOVCR8, //!< CPU supports `LOCK MOV CR8` (AMD CPUs).
|
||||||
kX86FeatureRDTSCP, //!< CPU has RDTSCP.
|
|
||||||
kX86FeatureCMOV, //!< CPU has CMOV.
|
kX86FeatureCMOV, //!< CPU has CMOV.
|
||||||
kX86FeatureCMPXCHG8B, //!< CPU has CMPXCHG8B.
|
kX86FeatureCMPXCHG8B, //!< CPU has CMPXCHG8B.
|
||||||
kX86FeatureCMPXCHG16B, //!< CPU has CMPXCHG16B (x64).
|
kX86FeatureCMPXCHG16B, //!< CPU has CMPXCHG16B (x64).
|
||||||
|
kX86FeatureMSR, //!< CPU has RDMSR/WRMSR.
|
||||||
|
kX86FeatureRDTSC, //!< CPU has RDTSC.
|
||||||
|
kX86FeatureRDTSCP, //!< CPU has RDTSCP.
|
||||||
kX86FeatureCLFLUSH, //!< CPU has CLFUSH.
|
kX86FeatureCLFLUSH, //!< CPU has CLFUSH.
|
||||||
kX86FeatureCLFLUSH_OPT, //!< CPU has CLFUSH (optimized).
|
kX86FeatureCLFLUSHOPT, //!< CPU has CLFUSHOPT.
|
||||||
kX86FeatureCLWB, //!< CPU has CLWB.
|
kX86FeatureCLWB, //!< CPU has CLWB.
|
||||||
kX86FeatureCLZERO, //!< CPU has CLZERO.
|
kX86FeatureCLZERO, //!< CPU has CLZERO.
|
||||||
kX86FeaturePCOMMIT, //!< CPU has PCOMMIT.
|
kX86FeaturePCOMMIT, //!< CPU has PCOMMIT.
|
||||||
kX86FeaturePREFETCH, //!< CPU has PREFETCH.
|
kX86FeaturePREFETCHW, //!< CPU has PREFETCHW.
|
||||||
kX86FeaturePREFETCHWT1, //!< CPU has PREFETCHWT1.
|
kX86FeaturePREFETCHWT1, //!< CPU has PREFETCHWT1.
|
||||||
kX86FeatureLAHF_SAHF, //!< CPU has LAHF/SAHF.
|
kX86FeatureLAHFSAHF, //!< CPU has LAHF/SAHF.
|
||||||
kX86FeatureFXSR, //!< CPU has FXSAVE/FXRSTOR.
|
kX86FeatureFXSR, //!< CPU has FXSAVE/FXRSTOR.
|
||||||
kX86FeatureFXSR_OPT, //!< CPU has FXSAVE/FXRSTOR (optimized).
|
kX86FeatureFXSROPT, //!< CPU has FXSAVE/FXRSTOR (optimized).
|
||||||
kX86FeatureMMX, //!< CPU has MMX.
|
kX86FeatureMMX, //!< CPU has MMX.
|
||||||
kX86FeatureMMX2, //!< CPU has extended MMX.
|
kX86FeatureMMX2, //!< CPU has extended MMX.
|
||||||
kX86Feature3DNOW, //!< CPU has 3DNOW!
|
kX86Feature3DNOW, //!< CPU has 3DNOW.
|
||||||
kX86Feature3DNOW2, //!< CPU has enhanced 3DNOW!
|
kX86Feature3DNOW2, //!< CPU has 3DNOW2 (enhanced).
|
||||||
|
kX86FeatureGEODE, //!< CPU has GEODE extensions (few additions to 3DNOW).
|
||||||
kX86FeatureSSE, //!< CPU has SSE.
|
kX86FeatureSSE, //!< CPU has SSE.
|
||||||
kX86FeatureSSE2, //!< CPU has SSE2.
|
kX86FeatureSSE2, //!< CPU has SSE2.
|
||||||
kX86FeatureSSE3, //!< CPU has SSE3.
|
kX86FeatureSSE3, //!< CPU has SSE3.
|
||||||
@@ -101,12 +105,13 @@ public:
|
|||||||
kX86FeatureSMAP, //!< CPU has SMAP (supervisor-mode access prevention).
|
kX86FeatureSMAP, //!< CPU has SMAP (supervisor-mode access prevention).
|
||||||
kX86FeatureSMEP, //!< CPU has SMEP (supervisor-mode execution prevention).
|
kX86FeatureSMEP, //!< CPU has SMEP (supervisor-mode execution prevention).
|
||||||
kX86FeatureSHA, //!< CPU has SHA-1 and SHA-256.
|
kX86FeatureSHA, //!< CPU has SHA-1 and SHA-256.
|
||||||
kX86FeatureXSAVE, //!< CPU has XSAVE support - XSAVE/XRSTOR, XSETBV/XGETBV, and XCR0.
|
kX86FeatureXSAVE, //!< CPU has XSAVE support - XSAVE/XRSTOR, XSETBV/XGETBV, and XCR.
|
||||||
kX86FeatureXSAVE_OS, //!< OS has enabled XSAVE, you can call XGETBV to get value of XCR0.
|
kX86FeatureXSAVEOPT, //!< CPU has XSAVEOPT support - XSAVEOPT/XSAVEOPT64.
|
||||||
|
kX86FeatureOSXSAVE, //!< OS has enabled XSAVE, you can call XGETBV to get XCR content.
|
||||||
kX86FeatureAVX, //!< CPU has AVX.
|
kX86FeatureAVX, //!< CPU has AVX.
|
||||||
kX86FeatureAVX2, //!< CPU has AVX2.
|
kX86FeatureAVX2, //!< CPU has AVX2.
|
||||||
kX86FeatureF16C, //!< CPU has F16C.
|
kX86FeatureF16C, //!< CPU has F16C.
|
||||||
kX86FeatureFMA3, //!< CPU has FMA3.
|
kX86FeatureFMA, //!< CPU has FMA.
|
||||||
kX86FeatureFMA4, //!< CPU has FMA4.
|
kX86FeatureFMA4, //!< CPU has FMA4.
|
||||||
kX86FeatureXOP, //!< CPU has XOP.
|
kX86FeatureXOP, //!< CPU has XOP.
|
||||||
kX86FeatureBMI, //!< CPU has BMI (bit manipulation instructions #1).
|
kX86FeatureBMI, //!< CPU has BMI (bit manipulation instructions #1).
|
||||||
|
|||||||
@@ -49,20 +49,24 @@ static const char errorMessages[] =
|
|||||||
"Invalid register kind\0"
|
"Invalid register kind\0"
|
||||||
"Invalid register's physical id\0"
|
"Invalid register's physical id\0"
|
||||||
"Invalid register's virtual id\0"
|
"Invalid register's virtual id\0"
|
||||||
"Invalid rex prefix\0"
|
"Invalid LOCK prefix\0"
|
||||||
|
"Invalid REP prefix\0"
|
||||||
|
"Invalid REX prefix\0"
|
||||||
"Invalid mask, expected {k}\0"
|
"Invalid mask, expected {k}\0"
|
||||||
"Invalid use of {k}\0"
|
"Invalid use of {k}\0"
|
||||||
"Invalid use of {k}{z}\0"
|
"Invalid use of {k}{z}\0"
|
||||||
"Invalid broadcast {1tox}\0"
|
"Invalid broadcast {1tox}\0"
|
||||||
"Invalid {sae} or {rc} option\0"
|
"Invalid {er} or {sae} option\0"
|
||||||
"Invalid address\0"
|
"Invalid address\0"
|
||||||
"Invalid address index\0"
|
"Invalid address index\0"
|
||||||
"Invalid address scale\0"
|
"Invalid address scale\0"
|
||||||
"Invalid use of 64-bit address\0"
|
"Invalid use of 64-bit address\0"
|
||||||
"Invalid displacement\0"
|
"Invalid displacement\0"
|
||||||
"Invalid segment\0"
|
"Invalid segment\0"
|
||||||
"Operand size mismatch\0"
|
"Invalid immediate value\0"
|
||||||
|
"Invalid operand size\0"
|
||||||
"Ambiguous operand size\0"
|
"Ambiguous operand size\0"
|
||||||
|
"Operand size mismatch\0"
|
||||||
"Invalid type-info\0"
|
"Invalid type-info\0"
|
||||||
"Invalid use of a low 8-bit GPB register\0"
|
"Invalid use of a low 8-bit GPB register\0"
|
||||||
"Invalid use of a 64-bit GPQ register in 32-bit mode\0"
|
"Invalid use of a 64-bit GPQ register in 32-bit mode\0"
|
||||||
|
|||||||
@@ -177,6 +177,10 @@ ASMJIT_ENUM(ErrorCode) {
|
|||||||
kErrorInvalidPhysId,
|
kErrorInvalidPhysId,
|
||||||
//! Invalid register's virtual id.
|
//! Invalid register's virtual id.
|
||||||
kErrorInvalidVirtId,
|
kErrorInvalidVirtId,
|
||||||
|
//! Invalid LOCK prefix.
|
||||||
|
kErrorInvalidLockPrefix,
|
||||||
|
//! Invalid REP prefix.
|
||||||
|
kErrorInvalidRepPrefix,
|
||||||
//! Invalid REX prefix.
|
//! Invalid REX prefix.
|
||||||
kErrorInvalidRexPrefix,
|
kErrorInvalidRexPrefix,
|
||||||
//! Invalid mask register (not 'k').
|
//! Invalid mask register (not 'k').
|
||||||
@@ -199,13 +203,18 @@ ASMJIT_ENUM(ErrorCode) {
|
|||||||
kErrorInvalidAddress64Bit,
|
kErrorInvalidAddress64Bit,
|
||||||
//! Invalid displacement (not encodable).
|
//! Invalid displacement (not encodable).
|
||||||
kErrorInvalidDisplacement,
|
kErrorInvalidDisplacement,
|
||||||
//! Invalid segment.
|
//! Invalid segment (X86).
|
||||||
kErrorInvalidSegment,
|
kErrorInvalidSegment,
|
||||||
|
|
||||||
//! Mismatching operand size (size of multiple operands doesn't match the operation size).
|
//! Invalid immediate (out of bounds on X86 and invalid pattern on ARM).
|
||||||
kErrorOperandSizeMismatch,
|
kErrorInvalidImmediate,
|
||||||
|
|
||||||
|
//! Invalid operand size.
|
||||||
|
kErrorInvalidOperandSize,
|
||||||
//! Ambiguous operand size (memory has zero size while it's required to determine the operation type.
|
//! Ambiguous operand size (memory has zero size while it's required to determine the operation type.
|
||||||
kErrorAmbiguousOperandSize,
|
kErrorAmbiguousOperandSize,
|
||||||
|
//! Mismatching operand size (size of multiple operands doesn't match the operation size).
|
||||||
|
kErrorOperandSizeMismatch,
|
||||||
|
|
||||||
//! Invalid TypeId.
|
//! Invalid TypeId.
|
||||||
kErrorInvalidTypeId,
|
kErrorInvalidTypeId,
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ struct IntTraits {
|
|||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
//! AsmJit utilities - integer, string, etc...
|
//! AsmJit utilities - integer, string, etc...
|
||||||
struct Utils {
|
namespace Utils {
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// [Float <-> Int]
|
// [Float <-> Int]
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -196,6 +196,18 @@ struct Utils {
|
|||||||
// [IsInt / IsUInt]
|
// [IsInt / IsUInt]
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//! Get whether the given integer `x` can be casted to a 4-bit signed integer.
|
||||||
|
template<typename T>
|
||||||
|
static ASMJIT_INLINE bool isInt4(T x) noexcept {
|
||||||
|
typedef typename IntTraits<T>::SignedType SignedType;
|
||||||
|
typedef typename IntTraits<T>::UnsignedType UnsignedType;
|
||||||
|
|
||||||
|
if (IntTraits<T>::kIsSigned)
|
||||||
|
return inInterval<SignedType>(SignedType(x), -8, 7);
|
||||||
|
else
|
||||||
|
return UnsignedType(x) <= UnsignedType(7U);
|
||||||
|
}
|
||||||
|
|
||||||
//! Get whether the given integer `x` can be casted to an 8-bit signed integer.
|
//! Get whether the given integer `x` can be casted to an 8-bit signed integer.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static ASMJIT_INLINE bool isInt8(T x) noexcept {
|
static ASMJIT_INLINE bool isInt8(T x) noexcept {
|
||||||
@@ -232,6 +244,17 @@ struct Utils {
|
|||||||
return sizeof(T) <= 2 || UnsignedType(x) <= UnsignedType(2147483647U);
|
return sizeof(T) <= 2 || UnsignedType(x) <= UnsignedType(2147483647U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Get whether the given integer `x` can be casted to a 4-bit unsigned integer.
|
||||||
|
template<typename T>
|
||||||
|
static ASMJIT_INLINE bool isUInt4(T x) noexcept {
|
||||||
|
typedef typename IntTraits<T>::UnsignedType UnsignedType;
|
||||||
|
|
||||||
|
if (IntTraits<T>::kIsSigned)
|
||||||
|
return x >= T(0) && x <= T(15);
|
||||||
|
else
|
||||||
|
return UnsignedType(x) <= UnsignedType(15U);
|
||||||
|
}
|
||||||
|
|
||||||
//! Get whether the given integer `x` can be casted to an 8-bit unsigned integer.
|
//! Get whether the given integer `x` can be casted to an 8-bit unsigned integer.
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static ASMJIT_INLINE bool isUInt8(T x) noexcept {
|
static ASMJIT_INLINE bool isUInt8(T x) noexcept {
|
||||||
@@ -386,6 +409,42 @@ struct Utils {
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
// [FirstBitOf]
|
||||||
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<uint64_t In>
|
||||||
|
struct FirstBitOfTImpl {
|
||||||
|
enum {
|
||||||
|
_shift = (In & ASMJIT_UINT64_C(0x0000FFFFFFFFFFFF)) == 0 ? 48 :
|
||||||
|
(In & ASMJIT_UINT64_C(0x00000000FFFFFFFF)) == 0 ? 32 :
|
||||||
|
(In & ASMJIT_UINT64_C(0x000000000000FFFF)) == 0 ? 16 : 0,
|
||||||
|
|
||||||
|
kValue = ((In >> _shift) & 0x0001) ? (_shift + 0) :
|
||||||
|
((In >> _shift) & 0x0002) ? (_shift + 1) :
|
||||||
|
((In >> _shift) & 0x0004) ? (_shift + 2) :
|
||||||
|
((In >> _shift) & 0x0008) ? (_shift + 3) :
|
||||||
|
((In >> _shift) & 0x0010) ? (_shift + 4) :
|
||||||
|
((In >> _shift) & 0x0020) ? (_shift + 5) :
|
||||||
|
((In >> _shift) & 0x0040) ? (_shift + 6) :
|
||||||
|
((In >> _shift) & 0x0080) ? (_shift + 7) :
|
||||||
|
((In >> _shift) & 0x0100) ? (_shift + 8) :
|
||||||
|
((In >> _shift) & 0x0200) ? (_shift + 9) :
|
||||||
|
((In >> _shift) & 0x0400) ? (_shift + 10) :
|
||||||
|
((In >> _shift) & 0x0800) ? (_shift + 11) :
|
||||||
|
((In >> _shift) & 0x1000) ? (_shift + 12) :
|
||||||
|
((In >> _shift) & 0x2000) ? (_shift + 13) :
|
||||||
|
((In >> _shift) & 0x4000) ? (_shift + 14) :
|
||||||
|
((In >> _shift) & 0x8000) ? (_shift + 15) : 0
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct FirstBitOfTImpl<0> {};
|
||||||
|
|
||||||
|
template<uint64_t In>
|
||||||
|
static ASMJIT_INLINE uint32_t firstBitOfT() noexcept { return FirstBitOfTImpl<In>::kValue; }
|
||||||
|
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
// [FindFirstBit]
|
// [FindFirstBit]
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
@@ -1000,7 +1059,7 @@ struct Utils {
|
|||||||
|
|
||||||
static ASMJIT_INLINE void writeI64a(void* p, int64_t x) noexcept { writeI64x<8>(p, x); }
|
static ASMJIT_INLINE void writeI64a(void* p, int64_t x) noexcept { writeI64x<8>(p, x); }
|
||||||
static ASMJIT_INLINE void writeI64u(void* p, int64_t x) noexcept { writeI64x<0>(p, x); }
|
static ASMJIT_INLINE void writeI64u(void* p, int64_t x) noexcept { writeI64x<0>(p, x); }
|
||||||
};
|
} // Utils namespace
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// [asmjit::UInt64]
|
// [asmjit::UInt64]
|
||||||
|
|||||||
@@ -322,7 +322,7 @@ static ASMJIT_INLINE uint32_t x86PackRegAndVvvvv(uint32_t regId, uint32_t vvvvvI
|
|||||||
}
|
}
|
||||||
|
|
||||||
static ASMJIT_INLINE uint32_t x86OpCodeLByVMem(const Operand_& op) noexcept {
|
static ASMJIT_INLINE uint32_t x86OpCodeLByVMem(const Operand_& op) noexcept {
|
||||||
return x86LLByRegType[static_cast<const X86Mem&>(op).getIndexType()];
|
return x86LLByRegType[op.as<X86Mem>().getIndexType()];
|
||||||
}
|
}
|
||||||
|
|
||||||
static ASMJIT_INLINE uint32_t x86OpCodeLBySize(uint32_t size) noexcept {
|
static ASMJIT_INLINE uint32_t x86OpCodeLBySize(uint32_t size) noexcept {
|
||||||
@@ -573,18 +573,18 @@ Error X86Assembler::_emit(uint32_t instId, const Operand_& o0, const Operand_& o
|
|||||||
|
|
||||||
// LOCK prefix.
|
// LOCK prefix.
|
||||||
if (options & X86Inst::kOptionLock) {
|
if (options & X86Inst::kOptionLock) {
|
||||||
if (ASMJIT_UNLIKELY(!(instFlags & X86Inst::kInstFlagLock)))
|
if (ASMJIT_UNLIKELY(!(instFlags & X86Inst::kFlagLock)))
|
||||||
goto InvalidInstruction;
|
goto InvalidLockPrefix;
|
||||||
EMIT_BYTE(0xF0);
|
EMIT_BYTE(0xF0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// REP / REPNZ prefix.
|
// REP / REPNZ prefix.
|
||||||
if (options & (X86Inst::kOptionRep | X86Inst::kOptionRepnz)) {
|
if (options & (X86Inst::kOptionRep | X86Inst::kOptionRepnz)) {
|
||||||
if (ASMJIT_UNLIKELY(!(instFlags & (X86Inst::kInstFlagRep | X86Inst::kInstFlagRepnz))))
|
if (ASMJIT_UNLIKELY(!(instFlags & (X86Inst::kFlagRep | X86Inst::kFlagRepnz))))
|
||||||
goto InvalidInstruction;
|
goto InvalidRepPrefix;
|
||||||
|
|
||||||
if (!_opExtra.isNone() && ASMJIT_UNLIKELY(!X86Reg::isGp(_opExtra, X86Gp::kIdCx)))
|
if (!_opExtra.isNone() && ASMJIT_UNLIKELY(!X86Reg::isGp(_opExtra, X86Gp::kIdCx)))
|
||||||
goto InvalidInstruction;
|
goto InvalidRepPrefix;
|
||||||
|
|
||||||
EMIT_BYTE((options & X86Inst::kOptionRepnz) ? 0xF2 : 0xF3);
|
EMIT_BYTE((options & X86Inst::kOptionRepnz) ? 0xF2 : 0xF3);
|
||||||
}
|
}
|
||||||
@@ -768,6 +768,31 @@ CaseX86M_GPB_MulDiv:
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case X86Inst::kEncodingX86Rm_Raw66H:
|
||||||
|
// We normally emit either [66|F2|F3], this instruction requires 66+[F2|F3].
|
||||||
|
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
||||||
|
opReg = o0.getId();
|
||||||
|
rbReg = o1.getId();
|
||||||
|
|
||||||
|
if (o0.getSize() == 2)
|
||||||
|
EMIT_BYTE(0x66);
|
||||||
|
else
|
||||||
|
ADD_REX_W_BY_SIZE(o0.getSize());
|
||||||
|
goto EmitX86R;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isign3 == ENC_OPS2(Reg, Mem)) {
|
||||||
|
opReg = o0.getId();
|
||||||
|
rmRel = &o1;
|
||||||
|
|
||||||
|
if (o0.getSize() == 2)
|
||||||
|
EMIT_BYTE(0x66);
|
||||||
|
else
|
||||||
|
ADD_REX_W_BY_SIZE(o0.getSize());
|
||||||
|
goto EmitX86M;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case X86Inst::kEncodingX86Mr:
|
case X86Inst::kEncodingX86Mr:
|
||||||
ADD_PREFIX_BY_SIZE(o0.getSize());
|
ADD_PREFIX_BY_SIZE(o0.getSize());
|
||||||
ASMJIT_FALLTHROUGH;
|
ASMJIT_FALLTHROUGH;
|
||||||
@@ -878,7 +903,7 @@ CaseX86M_GPB_MulDiv:
|
|||||||
if (instId == X86Inst::kIdAnd)
|
if (instId == X86Inst::kIdAnd)
|
||||||
size = 4;
|
size = 4;
|
||||||
else if (!Utils::isInt32(imVal))
|
else if (!Utils::isInt32(imVal))
|
||||||
goto InvalidInstruction;
|
goto InvalidImmediate;
|
||||||
}
|
}
|
||||||
ADD_REX_W_BY_SIZE(size);
|
ADD_REX_W_BY_SIZE(size);
|
||||||
}
|
}
|
||||||
@@ -1034,9 +1059,11 @@ CaseX86M_GPB_MulDiv:
|
|||||||
|
|
||||||
case X86Inst::kEncodingX86Crc:
|
case X86Inst::kEncodingX86Crc:
|
||||||
opReg = o0.getId();
|
opReg = o0.getId();
|
||||||
|
ADD_REX_W_BY_SIZE(o0.getSize());
|
||||||
|
|
||||||
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
if (isign3 == ENC_OPS2(Reg, Reg)) {
|
||||||
rbReg = o1.getId();
|
rbReg = o1.getId();
|
||||||
|
|
||||||
if (o1.getSize() == 1) {
|
if (o1.getSize() == 1) {
|
||||||
FIXUP_GPB(o1, rbReg);
|
FIXUP_GPB(o1, rbReg);
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
@@ -1046,7 +1073,6 @@ CaseX86M_GPB_MulDiv:
|
|||||||
if (o1.getSize() == 2) EMIT_BYTE(0x66);
|
if (o1.getSize() == 2) EMIT_BYTE(0x66);
|
||||||
|
|
||||||
opCode++;
|
opCode++;
|
||||||
ADD_REX_W_BY_SIZE(o1.getSize());
|
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1060,7 +1086,6 @@ CaseX86M_GPB_MulDiv:
|
|||||||
if (o1.getSize() == 2) EMIT_BYTE(0x66);
|
if (o1.getSize() == 2) EMIT_BYTE(0x66);
|
||||||
|
|
||||||
opCode += o1.getSize() != 1;
|
opCode += o1.getSize() != 1;
|
||||||
ADD_REX_W_BY_SIZE(o1.getSize());
|
|
||||||
goto EmitX86M;
|
goto EmitX86M;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1363,6 +1388,12 @@ CaseX86M_GPB_MulDiv:
|
|||||||
// GP <- CR
|
// GP <- CR
|
||||||
if (X86Reg::isCr(o1)) {
|
if (X86Reg::isCr(o1)) {
|
||||||
opCode = 0x20 | X86Inst::kOpCode_MM_0F;
|
opCode = 0x20 | X86Inst::kOpCode_MM_0F;
|
||||||
|
|
||||||
|
// Use `LOCK MOV` in 32-bit mode if CR8+ register is accessed (AMD extension).
|
||||||
|
if ((opReg & 0x8) && is32Bit()) {
|
||||||
|
EMIT_BYTE(0xF0);
|
||||||
|
opReg &= 0x7;
|
||||||
|
}
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1388,6 +1419,12 @@ CaseX86M_GPB_MulDiv:
|
|||||||
// CR <- GP
|
// CR <- GP
|
||||||
if (X86Reg::isCr(o0)) {
|
if (X86Reg::isCr(o0)) {
|
||||||
opCode = 0x22 | X86Inst::kOpCode_MM_0F;
|
opCode = 0x22 | X86Inst::kOpCode_MM_0F;
|
||||||
|
|
||||||
|
// Use `LOCK MOV` in 32-bit mode if CR8+ register is accessed (AMD extension).
|
||||||
|
if ((opReg & 0x8) && is32Bit()) {
|
||||||
|
EMIT_BYTE(0xF0);
|
||||||
|
opReg &= 0x7;
|
||||||
|
}
|
||||||
goto EmitX86R;
|
goto EmitX86R;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2101,16 +2138,16 @@ CaseFpuArith_Mem:
|
|||||||
if (isign3 == ENC_OPS1(Mem)) {
|
if (isign3 == ENC_OPS1(Mem)) {
|
||||||
rmRel = &o0;
|
rmRel = &o0;
|
||||||
|
|
||||||
if (o0.getSize() == 4 && commonData->hasFlag(X86Inst::kInstFlagFPU_M4)) {
|
if (o0.getSize() == 4 && commonData->hasFlag(X86Inst::kFlagFpuM32)) {
|
||||||
goto EmitX86M;
|
goto EmitX86M;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o0.getSize() == 8 && commonData->hasFlag(X86Inst::kInstFlagFPU_M8)) {
|
if (o0.getSize() == 8 && commonData->hasFlag(X86Inst::kFlagFpuM64)) {
|
||||||
opCode += 4;
|
opCode += 4;
|
||||||
goto EmitX86M;
|
goto EmitX86M;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o0.getSize() == 10 && commonData->hasFlag(X86Inst::kInstFlagFPU_M10)) {
|
if (o0.getSize() == 10 && commonData->hasFlag(X86Inst::kFlagFpuM80)) {
|
||||||
opCode = commonData->getAltOpCode();
|
opCode = commonData->getAltOpCode();
|
||||||
opReg = x86ExtractO(opCode);
|
opReg = x86ExtractO(opCode);
|
||||||
goto EmitX86M;
|
goto EmitX86M;
|
||||||
@@ -2130,16 +2167,16 @@ CaseFpuArith_Mem:
|
|||||||
opCode &= ~static_cast<uint32_t>(X86Inst::kOpCode_CDSHL_Mask);
|
opCode &= ~static_cast<uint32_t>(X86Inst::kOpCode_CDSHL_Mask);
|
||||||
|
|
||||||
rmRel = &o0;
|
rmRel = &o0;
|
||||||
if (o0.getSize() == 2 && commonData->hasFlag(X86Inst::kInstFlagFPU_M2)) {
|
if (o0.getSize() == 2 && commonData->hasFlag(X86Inst::kFlagFpuM16)) {
|
||||||
opCode += 4;
|
opCode += 4;
|
||||||
goto EmitX86M;
|
goto EmitX86M;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o0.getSize() == 4 && commonData->hasFlag(X86Inst::kInstFlagFPU_M4)) {
|
if (o0.getSize() == 4 && commonData->hasFlag(X86Inst::kFlagFpuM32)) {
|
||||||
goto EmitX86M;
|
goto EmitX86M;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o0.getSize() == 8 && commonData->hasFlag(X86Inst::kInstFlagFPU_M8)) {
|
if (o0.getSize() == 8 && commonData->hasFlag(X86Inst::kFlagFpuM64)) {
|
||||||
opCode = commonData->getAltOpCode() & ~static_cast<uint32_t>(X86Inst::kOpCode_CDSHL_Mask);
|
opCode = commonData->getAltOpCode() & ~static_cast<uint32_t>(X86Inst::kOpCode_CDSHL_Mask);
|
||||||
opReg = x86ExtractO(opCode);
|
opReg = x86ExtractO(opCode);
|
||||||
goto EmitX86M;
|
goto EmitX86M;
|
||||||
@@ -3947,6 +3984,9 @@ EmitVexEvexR:
|
|||||||
(x86ExtractLLMM(opCode, options)); // [........|.LL.....|Vvvvv..R|RBBmmmmm].
|
(x86ExtractLLMM(opCode, options)); // [........|.LL.....|Vvvvv..R|RBBmmmmm].
|
||||||
opReg &= 0x7;
|
opReg &= 0x7;
|
||||||
|
|
||||||
|
// Mark invalid VEX (force EVEX) case: // [@.......|.LL.....|Vvvvv..R|RBBmmmmm].
|
||||||
|
x |= (~commonData->getFlags() & X86Inst::kFlagVex) << (31 - Utils::firstBitOfT<X86Inst::kFlagVex>());
|
||||||
|
|
||||||
// Handle AVX512 options by a single branch.
|
// Handle AVX512 options by a single branch.
|
||||||
const uint32_t kAvx512Options = X86Inst::kOptionOpExtra |
|
const uint32_t kAvx512Options = X86Inst::kOptionOpExtra |
|
||||||
X86Inst::kOptionKZ |
|
X86Inst::kOptionKZ |
|
||||||
@@ -3966,13 +4006,13 @@ EmitVexEvexR:
|
|||||||
if (options & X86Inst::kOptionOpExtra)
|
if (options & X86Inst::kOptionOpExtra)
|
||||||
x |= _opExtra.getId() << 16;
|
x |= _opExtra.getId() << 16;
|
||||||
|
|
||||||
x |= options & X86Inst::kOptionKZ; // [........|zLL..aaa|Vvvvv..R|RBBmmmmm].
|
x |= options & X86Inst::kOptionKZ; // [@.......|zLL..aaa|Vvvvv..R|RBBmmmmm].
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if EVEX is required by checking bits in `x` : [........|xx...xxx|x......x|.x.x....].
|
// Check if EVEX is required by checking bits in `x` : [@.......|xx...xxx|x......x|.x.x....].
|
||||||
if (x & 0x00C78150U) {
|
if (x & 0x80C78150U) {
|
||||||
uint32_t y = ((x << 4) & 0x00080000U) | // [........|....V...|........|........].
|
uint32_t y = ((x << 4) & 0x00080000U) | // [@.......|....V...|........|........].
|
||||||
((x >> 4) & 0x00000010U) ; // [........|....V...|........|...R....].
|
((x >> 4) & 0x00000010U) ; // [@.......|....V...|........|...R....].
|
||||||
x = (x & 0x00FF78E3U) | y; // [........|zLL.Vaaa|0vvvv000|RBBR00mm].
|
x = (x & 0x00FF78E3U) | y; // [........|zLL.Vaaa|0vvvv000|RBBR00mm].
|
||||||
x = (x << 8) | // [zLL.Vaaa|0vvvv000|RBBR00mm|00000000].
|
x = (x << 8) | // [zLL.Vaaa|0vvvv000|RBBR00mm|00000000].
|
||||||
((opCode >> kSHR_W_PP) & 0x00830000U) | // [zLL.Vaaa|Wvvvv0pp|RBBR00mm|00000000].
|
((opCode >> kSHR_W_PP) & 0x00830000U) | // [zLL.Vaaa|Wvvvv0pp|RBBR00mm|00000000].
|
||||||
@@ -4058,6 +4098,9 @@ EmitVexEvexM:
|
|||||||
(x86ExtractLLMM(opCode, options)); // [........|.LL.X...|Vvvvv..R|RXBmmmmm].
|
(x86ExtractLLMM(opCode, options)); // [........|.LL.X...|Vvvvv..R|RXBmmmmm].
|
||||||
opReg &= 0x07U;
|
opReg &= 0x07U;
|
||||||
|
|
||||||
|
// Mark invalid VEX (force EVEX) case: // [@.......|.LL.X...|Vvvvv..R|RXBmmmmm].
|
||||||
|
x |= (~commonData->getFlags() & X86Inst::kFlagVex) << (31 - Utils::firstBitOfT<X86Inst::kFlagVex>());
|
||||||
|
|
||||||
// Handle AVX512 options by a single branch.
|
// Handle AVX512 options by a single branch.
|
||||||
const uint32_t kAvx512Options = X86Inst::kOptionOpExtra |
|
const uint32_t kAvx512Options = X86Inst::kOptionOpExtra |
|
||||||
X86Inst::kOption1ToX |
|
X86Inst::kOption1ToX |
|
||||||
@@ -4075,15 +4118,15 @@ EmitVexEvexM:
|
|||||||
if (options & X86Inst::kOptionOpExtra)
|
if (options & X86Inst::kOptionOpExtra)
|
||||||
x |= _opExtra.getId() << 16;
|
x |= _opExtra.getId() << 16;
|
||||||
|
|
||||||
x |= options & (X86Inst::kOption1ToX | // [........|.LLbXaaa|Vvvvv..R|RXBmmmmm].
|
x |= options & (X86Inst::kOption1ToX | // [@.......|.LLbXaaa|Vvvvv..R|RXBmmmmm].
|
||||||
X86Inst::kOptionKZ ); // [........|zLLbXaaa|Vvvvv..R|RXBmmmmm].
|
X86Inst::kOptionKZ ); // [@.......|zLLbXaaa|Vvvvv..R|RXBmmmmm].
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if EVEX is required by checking bits in `x` : [........|xx.xxxxx|x......x|...x....].
|
// Check if EVEX is required by checking bits in `x` : [@.......|xx.xxxxx|x......x|...x....].
|
||||||
if (x & 0x00DF8110U) {
|
if (x & 0x80DF8110U) {
|
||||||
uint32_t y = ((x << 4) & 0x00080000U) | // [........|....V...|........|........].
|
uint32_t y = ((x << 4) & 0x00080000U) | // [@.......|....V...|........|........].
|
||||||
((x >> 4) & 0x00000010U) ; // [........|....V...|........|...R....].
|
((x >> 4) & 0x00000010U) ; // [@.......|....V...|........|...R....].
|
||||||
x = (x & 0xFFFF78E3U) | y; // [........|zLLbVaaa|0vvvv000|RXBR00mm].
|
x = (x & 0x00FF78E3U) | y; // [........|zLLbVaaa|0vvvv000|RXBR00mm].
|
||||||
x = (x << 8) | // [zLLbVaaa|0vvvv000|RBBR00mm|00000000].
|
x = (x << 8) | // [zLLbVaaa|0vvvv000|RBBR00mm|00000000].
|
||||||
((opCode >> kSHR_W_PP) & 0x00830000U) | // [zLLbVaaa|Wvvvv0pp|RBBR00mm|00000000].
|
((opCode >> kSHR_W_PP) & 0x00830000U) | // [zLLbVaaa|Wvvvv0pp|RBBR00mm|00000000].
|
||||||
((opCode >> kSHR_W_EW) & 0x00800000U) ; // [zLLbVaaa|Wvvvv0pp|RBBR00mm|00000000] (added EVEX.W).
|
((opCode >> kSHR_W_EW) & 0x00800000U) ; // [zLLbVaaa|Wvvvv0pp|RBBR00mm|00000000] (added EVEX.W).
|
||||||
@@ -4138,7 +4181,7 @@ EmitVexEvexM:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MOD|SIB address.
|
// MOD|SIB address.
|
||||||
if (!commonData->hasFlag(X86Inst::kInstFlagVM))
|
if (!commonData->hasFlag(X86Inst::kFlagVsib))
|
||||||
goto EmitModSib;
|
goto EmitModSib;
|
||||||
|
|
||||||
// MOD|VSIB address without INDEX is invalid.
|
// MOD|VSIB address without INDEX is invalid.
|
||||||
@@ -4150,7 +4193,7 @@ EmitVexEvexM:
|
|||||||
// [Emit - Jmp/Jcc/Call]
|
// [Emit - Jmp/Jcc/Call]
|
||||||
// --------------------------------------------------------------------------
|
// --------------------------------------------------------------------------
|
||||||
|
|
||||||
// TODO: Should be adjusted after there support for multiple sections feature is added.
|
// TODO: Should be adjusted after the support for multiple sections feature is added.
|
||||||
EmitJmpCall:
|
EmitJmpCall:
|
||||||
{
|
{
|
||||||
// Emit REX prefix if asked for (64-bit only).
|
// Emit REX prefix if asked for (64-bit only).
|
||||||
@@ -4392,6 +4435,8 @@ ERROR_HANDLER(NoHeapMemory)
|
|||||||
ERROR_HANDLER(InvalidArgument)
|
ERROR_HANDLER(InvalidArgument)
|
||||||
ERROR_HANDLER(InvalidLabel)
|
ERROR_HANDLER(InvalidLabel)
|
||||||
ERROR_HANDLER(InvalidInstruction)
|
ERROR_HANDLER(InvalidInstruction)
|
||||||
|
ERROR_HANDLER(InvalidLockPrefix)
|
||||||
|
ERROR_HANDLER(InvalidRepPrefix)
|
||||||
ERROR_HANDLER(InvalidRexPrefix)
|
ERROR_HANDLER(InvalidRexPrefix)
|
||||||
ERROR_HANDLER(InvalidBroadcast)
|
ERROR_HANDLER(InvalidBroadcast)
|
||||||
ERROR_HANDLER(InvalidEROrSAE)
|
ERROR_HANDLER(InvalidEROrSAE)
|
||||||
@@ -4400,6 +4445,7 @@ ERROR_HANDLER(InvalidAddressIndex)
|
|||||||
ERROR_HANDLER(InvalidAddress64Bit)
|
ERROR_HANDLER(InvalidAddress64Bit)
|
||||||
ERROR_HANDLER(InvalidDisplacement)
|
ERROR_HANDLER(InvalidDisplacement)
|
||||||
ERROR_HANDLER(InvalidSegment)
|
ERROR_HANDLER(InvalidSegment)
|
||||||
|
ERROR_HANDLER(InvalidImmediate)
|
||||||
ERROR_HANDLER(OperandSizeMismatch)
|
ERROR_HANDLER(OperandSizeMismatch)
|
||||||
ERROR_HANDLER(AmbiguousOperandSize)
|
ERROR_HANDLER(AmbiguousOperandSize)
|
||||||
ERROR_HANDLER(NotConsecutiveRegs)
|
ERROR_HANDLER(NotConsecutiveRegs)
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -34,35 +34,36 @@ namespace x86regs {}
|
|||||||
namespace x86defs {
|
namespace x86defs {
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// [asmjit::x86defs::SpecialRegFlags]
|
// [asmjit::x86defs::SpecialRegs]
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
//! Flags describing special registers and/or their parts.
|
//! Flags describing special registers and/or their parts.
|
||||||
ASMJIT_ENUM(SpecialRegFlags) {
|
ASMJIT_ENUM(SpecialRegs) {
|
||||||
kSpecialReg_Flags_CF = 0x00000001U, //!< [R|E]FLAGS - Carry flag.
|
kSpecialReg_FLAGS_CF = 0x00000001U, //!< [R|E]FLAGS - Carry flag.
|
||||||
kSpecialReg_Flags_PF = 0x00000002U, //!< [R|E]FLAGS - Parity flag.
|
kSpecialReg_FLAGS_PF = 0x00000002U, //!< [R|E]FLAGS - Parity flag.
|
||||||
kSpecialReg_Flags_AF = 0x00000004U, //!< [R|E]FLAGS - Adjust flag.
|
kSpecialReg_FLAGS_AF = 0x00000004U, //!< [R|E]FLAGS - Adjust flag.
|
||||||
kSpecialReg_Flags_ZF = 0x00000008U, //!< [R|E]FLAGS - Zero flag.
|
kSpecialReg_FLAGS_ZF = 0x00000008U, //!< [R|E]FLAGS - Zero flag.
|
||||||
kSpecialReg_Flags_SF = 0x00000010U, //!< [R|E]FLAGS - Sign flag.
|
kSpecialReg_FLAGS_SF = 0x00000010U, //!< [R|E]FLAGS - Sign flag.
|
||||||
kSpecialReg_Flags_TF = 0x00000020U, //!< [R|E]FLAGS - Trap flag.
|
kSpecialReg_FLAGS_TF = 0x00000020U, //!< [R|E]FLAGS - Trap flag.
|
||||||
kSpecialReg_Flags_IF = 0x00000040U, //!< [R|E]FLAGS - Interrupt enable flag.
|
kSpecialReg_FLAGS_IF = 0x00000040U, //!< [R|E]FLAGS - Interrupt enable flag.
|
||||||
kSpecialReg_Flags_DF = 0x00000080U, //!< [R|E]FLAGS - Direction flag.
|
kSpecialReg_FLAGS_DF = 0x00000080U, //!< [R|E]FLAGS - Direction flag.
|
||||||
kSpecialReg_Flags_OF = 0x00000100U, //!< [R|E]FLAGS - Overflow flag.
|
kSpecialReg_FLAGS_OF = 0x00000100U, //!< [R|E]FLAGS - Overflow flag.
|
||||||
kSpecialReg_Flags_AC = 0x00000200U, //!< [R|E]FLAGS - Alignment check.
|
kSpecialReg_FLAGS_AC = 0x00000200U, //!< [R|E]FLAGS - Alignment check.
|
||||||
kSpecialReg_Flags_Sys = 0x00000400U, //!< [R|E]FLAGS - System flags.
|
kSpecialReg_FLAGS_SYS = 0x00000400U, //!< [R|E]FLAGS - System flags.
|
||||||
|
|
||||||
kSpecialReg_X87CW_Exc = 0x00000800U, //!< X87 Control Word - Exception control.
|
kSpecialReg_X87CW_EXC = 0x00000800U, //!< X87 Control Word - Exception control.
|
||||||
kSpecialReg_X87CW_PC = 0x00001000U, //!< X87 Control Word - Precision control.
|
kSpecialReg_X87CW_PC = 0x00001000U, //!< X87 Control Word - Precision control.
|
||||||
kSpecialReg_X87CW_RC = 0x00002000U, //!< X87 Control Word - Rounding control.
|
kSpecialReg_X87CW_RC = 0x00002000U, //!< X87 Control Word - Rounding control.
|
||||||
|
|
||||||
kSpecialReg_X87SW_Exc = 0x00004000U, //!< X87 Status Word - Exception flags.
|
kSpecialReg_X87SW_EXC = 0x00004000U, //!< X87 Status Word - Exception flags.
|
||||||
kSpecialReg_X87SW_C0 = 0x00008000U, //!< X87 Status Word - C0 flag.
|
kSpecialReg_X87SW_C0 = 0x00008000U, //!< X87 Status Word - C0 flag.
|
||||||
kSpecialReg_X87SW_C1 = 0x00010000U, //!< X87 Status Word - C1 flag.
|
kSpecialReg_X87SW_C1 = 0x00010000U, //!< X87 Status Word - C1 flag.
|
||||||
kSpecialReg_X87SW_C2 = 0x00020000U, //!< X87 Status Word - C2 flag.
|
kSpecialReg_X87SW_C2 = 0x00020000U, //!< X87 Status Word - C2 flag.
|
||||||
kSpecialReg_X87SW_Top = 0x00040000U, //!< X87 Status Word - Top of the FPU stack.
|
kSpecialReg_X87SW_TOP = 0x00040000U, //!< X87 Status Word - Top of the FPU stack.
|
||||||
kSpecialReg_X87SW_C3 = 0x00080000U, //!< X87 Status Word - C3 flag.
|
kSpecialReg_X87SW_C3 = 0x00080000U, //!< X87 Status Word - C3 flag.
|
||||||
|
|
||||||
kSpecialReg_XCR = 0x00100000U //!< XCR register(s).
|
kSpecialReg_MSR = 0x00100000U, //!< MSR register.
|
||||||
|
kSpecialReg_XCR = 0x00200000U //!< XCR register.
|
||||||
};
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -599,7 +599,7 @@ ASMJIT_FAVOR_SIZE Error X86Logging::formatInstruction(
|
|||||||
if (options & (X86Inst::kOptionRep | X86Inst::kOptionRepnz)) {
|
if (options & (X86Inst::kOptionRep | X86Inst::kOptionRepnz)) {
|
||||||
const char* rep = "repnz ";
|
const char* rep = "repnz ";
|
||||||
if ((options & (X86Inst::kOptionRep | X86Inst::kOptionRepnz)) == X86Inst::kOptionRep)
|
if ((options & (X86Inst::kOptionRep | X86Inst::kOptionRepnz)) == X86Inst::kOptionRep)
|
||||||
rep = instInfo.hasFlag(X86Inst::kInstFlagRepnz) ? "repz " : "rep ";
|
rep = instInfo.hasFlag(X86Inst::kFlagRepnz) ? "repz " : "rep ";
|
||||||
|
|
||||||
sb.appendString(rep);
|
sb.appendString(rep);
|
||||||
if (!opExtra.isNone()) {
|
if (!opExtra.isNone()) {
|
||||||
|
|||||||
@@ -132,9 +132,9 @@ UNIT(x86_operand) {
|
|||||||
EXPECT(x86::zmm6.getKind() == X86Reg::kKindVec);
|
EXPECT(x86::zmm6.getKind() == X86Reg::kKindVec);
|
||||||
EXPECT(x86::zmm6.isVec());
|
EXPECT(x86::zmm6.isVec());
|
||||||
|
|
||||||
INFO("Checking XYZ register properties");
|
INFO("Checking VEC register properties");
|
||||||
EXPECT(X86Vec().isReg() == false);
|
EXPECT(X86Vec().isReg() == false);
|
||||||
// Converts a XYZ register to a type of the passed register, but keeps the ID.
|
// Converts a VEC register to a type of the passed register, but keeps the ID.
|
||||||
EXPECT(x86::xmm4.cloneAs(x86::ymm10) == x86::ymm4);
|
EXPECT(x86::xmm4.cloneAs(x86::ymm10) == x86::ymm4);
|
||||||
EXPECT(x86::xmm4.cloneAs(x86::zmm11) == x86::zmm4);
|
EXPECT(x86::xmm4.cloneAs(x86::zmm11) == x86::zmm4);
|
||||||
EXPECT(x86::ymm5.cloneAs(x86::xmm12) == x86::xmm5);
|
EXPECT(x86::ymm5.cloneAs(x86::xmm12) == x86::xmm5);
|
||||||
|
|||||||
@@ -73,8 +73,8 @@ static ASMJIT_INLINE const X86SpecialInst* X86SpecialInst_get(uint32_t instId, c
|
|||||||
static const X86SpecialInst instPcmpistri[] = { R(kAny), R(kAny), NONE(), W(X86Gp::kIdCx), R(X86Gp::kIdAx), R(X86Gp::kIdDx) };
|
static const X86SpecialInst instPcmpistri[] = { R(kAny), R(kAny), NONE(), W(X86Gp::kIdCx), R(X86Gp::kIdAx), R(X86Gp::kIdDx) };
|
||||||
static const X86SpecialInst instPcmpistrm[] = { R(kAny), R(kAny), NONE(), W(0) , R(X86Gp::kIdAx), R(X86Gp::kIdDx) };
|
static const X86SpecialInst instPcmpistrm[] = { R(kAny), R(kAny), NONE(), W(0) , R(X86Gp::kIdAx), R(X86Gp::kIdDx) };
|
||||||
static const X86SpecialInst instXsaveXrstor[] = { W(kAny), R(X86Gp::kIdDx), R(X86Gp::kIdAx) };
|
static const X86SpecialInst instXsaveXrstor[] = { W(kAny), R(X86Gp::kIdDx), R(X86Gp::kIdAx) };
|
||||||
static const X86SpecialInst instXgetbv[] = { W(X86Gp::kIdDx), W(X86Gp::kIdAx), R(X86Gp::kIdCx) };
|
static const X86SpecialInst instReadMR[] = { W(X86Gp::kIdDx), W(X86Gp::kIdAx), R(X86Gp::kIdCx) };
|
||||||
static const X86SpecialInst instXsetbv[] = { R(X86Gp::kIdDx), R(X86Gp::kIdAx), R(X86Gp::kIdCx) };
|
static const X86SpecialInst instWriteMR[] = { R(X86Gp::kIdDx), R(X86Gp::kIdAx), R(X86Gp::kIdCx) };
|
||||||
|
|
||||||
static const X86SpecialInst instCmps[] = { X(X86Gp::kIdSi), X(X86Gp::kIdDi) };
|
static const X86SpecialInst instCmps[] = { X(X86Gp::kIdSi), X(X86Gp::kIdDi) };
|
||||||
static const X86SpecialInst instLods[] = { W(X86Gp::kIdAx), X(X86Gp::kIdSi) };
|
static const X86SpecialInst instLods[] = { W(X86Gp::kIdAx), X(X86Gp::kIdSi) };
|
||||||
@@ -160,8 +160,11 @@ static ASMJIT_INLINE const X86SpecialInst* X86SpecialInst_get(uint32_t instId, c
|
|||||||
case X86Inst::kIdXsave64 :
|
case X86Inst::kIdXsave64 :
|
||||||
case X86Inst::kIdXsaveopt :
|
case X86Inst::kIdXsaveopt :
|
||||||
case X86Inst::kIdXsaveopt64 : return instXsaveXrstor;
|
case X86Inst::kIdXsaveopt64 : return instXsaveXrstor;
|
||||||
case X86Inst::kIdXgetbv : return instXgetbv;
|
case X86Inst::kIdRdmsr :
|
||||||
case X86Inst::kIdXsetbv : return instXsetbv;
|
case X86Inst::kIdRdpmc :
|
||||||
|
case X86Inst::kIdXgetbv : return instReadMR;
|
||||||
|
case X86Inst::kIdWrmsr :
|
||||||
|
case X86Inst::kIdXsetbv : return instWriteMR;
|
||||||
default : return nullptr;
|
default : return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1492,14 +1495,11 @@ _NextGroup:
|
|||||||
const X86Inst::CommonData& commonData = inst.getCommonData();
|
const X86Inst::CommonData& commonData = inst.getCommonData();
|
||||||
const X86SpecialInst* special = nullptr;
|
const X86SpecialInst* special = nullptr;
|
||||||
|
|
||||||
if (inst.isAvxFamily())
|
|
||||||
_avxEnabled = true;
|
|
||||||
|
|
||||||
// Collect instruction flags and merge all 'TiedReg's.
|
// Collect instruction flags and merge all 'TiedReg's.
|
||||||
if (commonData.isFp())
|
if (commonData.isFpu())
|
||||||
flags |= CBNode::kFlagIsFp;
|
flags |= CBNode::kFlagIsFp;
|
||||||
|
|
||||||
if (commonData.isSpecial() && (special = X86SpecialInst_get(instId, opArray, opCount)) != nullptr)
|
if (commonData.hasFixedRM() && (special = X86SpecialInst_get(instId, opArray, opCount)) != nullptr)
|
||||||
flags |= CBNode::kFlagIsSpecial;
|
flags |= CBNode::kFlagIsSpecial;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < opCount; i++) {
|
for (uint32_t i = 0; i < opCount; i++) {
|
||||||
@@ -1575,14 +1575,14 @@ _NextGroup:
|
|||||||
// Manually forcing write-only.
|
// Manually forcing write-only.
|
||||||
combinedFlags = outFlags;
|
combinedFlags = outFlags;
|
||||||
}
|
}
|
||||||
else if (commonData.isWO()) {
|
else if (commonData.isUseW()) {
|
||||||
// Write-only instruction.
|
// Write-only instruction.
|
||||||
uint32_t movSize = commonData.getWriteSize();
|
uint32_t movSize = commonData.getWriteSize();
|
||||||
uint32_t regSize = vreg->getSize();
|
uint32_t regSize = vreg->getSize();
|
||||||
|
|
||||||
// Exception - If the source operand is a memory location
|
// Exception - If the source operand is a memory location
|
||||||
// promote move size into 16 bytes.
|
// promote move size into 16 bytes.
|
||||||
if (commonData.isZeroIfMem() && opArray[1].isMem())
|
if (opArray[1].isMem() && inst.getOperationData().isMovSsSd())
|
||||||
movSize = 16;
|
movSize = 16;
|
||||||
|
|
||||||
if (static_cast<const X86Reg*>(op)->isGp()) {
|
if (static_cast<const X86Reg*>(op)->isGp()) {
|
||||||
@@ -1607,7 +1607,7 @@ _NextGroup:
|
|||||||
combinedFlags = outFlags;
|
combinedFlags = outFlags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (commonData.isRO()) {
|
else if (commonData.isUseR()) {
|
||||||
// Comparison/Test instructions don't modify any operand.
|
// Comparison/Test instructions don't modify any operand.
|
||||||
combinedFlags = inFlags;
|
combinedFlags = inFlags;
|
||||||
}
|
}
|
||||||
@@ -1624,7 +1624,7 @@ _NextGroup:
|
|||||||
ASMJIT_ASSERT(instId != X86Inst::kIdIdiv);
|
ASMJIT_ASSERT(instId != X86Inst::kIdIdiv);
|
||||||
|
|
||||||
// Xchg/Xadd/Imul.
|
// Xchg/Xadd/Imul.
|
||||||
if (commonData.isXchg() || (instId == X86Inst::kIdImul && opCount == 3 && i == 1))
|
if (commonData.isUseXX() || (instId == X86Inst::kIdImul && opCount == 3 && i == 1))
|
||||||
combinedFlags = inFlags | outFlags;
|
combinedFlags = inFlags | outFlags;
|
||||||
}
|
}
|
||||||
tied->flags |= combinedFlags;
|
tied->flags |= combinedFlags;
|
||||||
@@ -1651,7 +1651,7 @@ _NextGroup:
|
|||||||
// Default for the first operand.
|
// Default for the first operand.
|
||||||
combinedFlags = inFlags | outFlags;
|
combinedFlags = inFlags | outFlags;
|
||||||
|
|
||||||
if (commonData.isWO()) {
|
if (commonData.isUseW()) {
|
||||||
// Move to memory - setting the right flags is important
|
// Move to memory - setting the right flags is important
|
||||||
// as if it's just move to the register. It's just a bit
|
// as if it's just move to the register. It's just a bit
|
||||||
// simpler as there are no special cases.
|
// simpler as there are no special cases.
|
||||||
@@ -1661,7 +1661,7 @@ _NextGroup:
|
|||||||
if (movSize >= regSize)
|
if (movSize >= regSize)
|
||||||
combinedFlags = outFlags;
|
combinedFlags = outFlags;
|
||||||
}
|
}
|
||||||
else if (commonData.isRO()) {
|
else if (commonData.isUseR()) {
|
||||||
// Comparison/Test instructions don't modify any operand.
|
// Comparison/Test instructions don't modify any operand.
|
||||||
combinedFlags = inFlags;
|
combinedFlags = inFlags;
|
||||||
}
|
}
|
||||||
@@ -1671,7 +1671,7 @@ _NextGroup:
|
|||||||
combinedFlags = inFlags;
|
combinedFlags = inFlags;
|
||||||
|
|
||||||
// Handle Xchg instruction (modifies both operands).
|
// Handle Xchg instruction (modifies both operands).
|
||||||
if (commonData.isXchg())
|
if (commonData.isUseXX())
|
||||||
combinedFlags = inFlags | outFlags;
|
combinedFlags = inFlags | outFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1717,6 +1717,10 @@ _NextGroup:
|
|||||||
if (tiedTotal == 1 && opCount >= 2 && opArray[0].isVirtReg() && opArray[1].isVirtReg() && !node->hasMemOp())
|
if (tiedTotal == 1 && opCount >= 2 && opArray[0].isVirtReg() && opArray[1].isVirtReg() && !node->hasMemOp())
|
||||||
X86RAPass_prepareSingleVarInst(instId, &agTmp[0]);
|
X86RAPass_prepareSingleVarInst(instId, &agTmp[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Turn on AVX if the instruction operates on XMM|YMM|ZMM registers and uses VEX|EVEX prefix.
|
||||||
|
if (tiedCount.getVec() && commonData.hasFlag(X86Inst::kFlagVex | X86Inst::kFlagEvex))
|
||||||
|
_avxEnabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Operand_& opExtra = node->getOpExtra();
|
const Operand_& opExtra = node->getOpExtra();
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
// [AsmJit]
|
|
||||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
|
||||||
//
|
|
||||||
// [License]
|
|
||||||
// Zlib - See LICENSE.md file in the package.
|
|
||||||
|
|
||||||
// [Export]
|
|
||||||
#define ASMJIT_EXPORTS
|
|
||||||
|
|
||||||
// [Guard]
|
|
||||||
#include "../asmjit_build.h"
|
|
||||||
#if defined(ASMJIT_BUILD_X86) && !defined(ASMJIT_DISABLE_BUILDER)
|
|
||||||
|
|
||||||
// [Dependencies]
|
|
||||||
#include "../x86/x86inst.h"
|
|
||||||
#include "../x86/x86operand.h"
|
|
||||||
#include "../x86/x86ssetoavxpass_p.h"
|
|
||||||
|
|
||||||
// [Api-Begin]
|
|
||||||
#include "../asmjit_apibegin.h"
|
|
||||||
|
|
||||||
namespace asmjit {
|
|
||||||
|
|
||||||
// ============================================================================
|
|
||||||
// [asmjit::X86SseToAvxPass]
|
|
||||||
// ============================================================================
|
|
||||||
|
|
||||||
class X86SseToAvxPass : public CBPass {
|
|
||||||
ASMJIT_NONCOPYABLE(X86SseToAvxPass)
|
|
||||||
public:
|
|
||||||
X86SseToAvxPass() noexcept : CBPass("SseToAvx") {}
|
|
||||||
virtual Error process(Zone* zone) noexcept override;
|
|
||||||
|
|
||||||
enum ProbeMask {
|
|
||||||
kProbeMmx = 1U << X86Reg::kRegMm, //!< Instruction uses MMX registers.
|
|
||||||
kProbeXmm = 1U << X86Reg::kRegXmm //!< Instruction uses XMM registers.
|
|
||||||
};
|
|
||||||
|
|
||||||
static ASMJIT_INLINE uint32_t probeRegs(const Operand* opArray, uint32_t opCount) noexcept {
|
|
||||||
uint32_t mask = 0;
|
|
||||||
for (uint32_t i = 0; i < opCount; i++) {
|
|
||||||
const Operand& op = opArray[i];
|
|
||||||
if (!op.isReg()) continue;
|
|
||||||
mask |= Utils::mask(static_cast<const Reg&>(op).getType());
|
|
||||||
}
|
|
||||||
return mask;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Error X86SseToAvxPass::process(Zone* zone) noexcept {
|
|
||||||
ASMJIT_UNUSED(zone);
|
|
||||||
|
|
||||||
CBNode* node_ = cb()->getFirstNode();
|
|
||||||
while (node_) {
|
|
||||||
if (node_->getType() == CBNode::kNodeInst) {
|
|
||||||
CBInst* node = static_cast<CBInst*>(node_);
|
|
||||||
uint32_t instId = node->getInstId();
|
|
||||||
|
|
||||||
// Skip invalid and high-level instructions; we don't care here.
|
|
||||||
if (!X86Inst::isDefinedId(instId)) continue;
|
|
||||||
|
|
||||||
// Skip non-SSE instructions.
|
|
||||||
const X86Inst& instData = X86Inst::getInst(instId);
|
|
||||||
if (!instData.isSseFamily()) continue;
|
|
||||||
|
|
||||||
// Skip instructions that don't use XMM registers.
|
|
||||||
uint32_t regs = probeRegs(node->getOpArray(), node->getOpCount());
|
|
||||||
if (!(regs & kProbeXmm)) continue;
|
|
||||||
|
|
||||||
if (!(regs & kProbeMmx)) {
|
|
||||||
// This is the common case.
|
|
||||||
|
|
||||||
// TODO: Wait for some fixes in CBInst first.
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// If this instruction uses MMX register it means that it's a conversion
|
|
||||||
// between MMX and XMM (and vice versa), this cannot be directly translated
|
|
||||||
// to AVX as there is no such AVX instruction that works with MMX registers.
|
|
||||||
|
|
||||||
// TODO: Needs a mem-slot to be able to do this.
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
node_ = node_->getNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
return kErrorOk;
|
|
||||||
}
|
|
||||||
|
|
||||||
Error X86SseToAvxPassInit::add(CodeBuilder* cb) noexcept { return cb->addPassT<X86SseToAvxPass>(); }
|
|
||||||
|
|
||||||
} // asmjit namespace
|
|
||||||
|
|
||||||
// [Api-End]
|
|
||||||
#include "../asmjit_apiend.h"
|
|
||||||
|
|
||||||
// [Guard]
|
|
||||||
#endif // ASMJIT_BUILD_X86 && !ASMJIT_DISABLE_BUILDER
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
// [AsmJit]
|
|
||||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
|
||||||
//
|
|
||||||
// [License]
|
|
||||||
// Zlib - See LICENSE.md file in the package.
|
|
||||||
|
|
||||||
// [Guard]
|
|
||||||
#ifndef _ASMJIT_X86_X86SSETOAVXPASS_P_H
|
|
||||||
#define _ASMJIT_X86_X86SSETOAVXPASS_P_H
|
|
||||||
|
|
||||||
#include "../asmjit_build.h"
|
|
||||||
#if !defined(ASMJIT_DISABLE_BUIILDER)
|
|
||||||
|
|
||||||
// [Dependencies]
|
|
||||||
#include "../base/codebuilder.h"
|
|
||||||
|
|
||||||
// [Api-Begin]
|
|
||||||
#include "../asmjit_apibegin.h"
|
|
||||||
|
|
||||||
namespace asmjit {
|
|
||||||
|
|
||||||
//! \addtogroup asmjit_x86
|
|
||||||
//! \{
|
|
||||||
|
|
||||||
struct X86SseToAvxPassInit {
|
|
||||||
static Error add(CodeBuilder* cb) noexcept;
|
|
||||||
};
|
|
||||||
|
|
||||||
//! \}
|
|
||||||
|
|
||||||
} // asmjit namespace
|
|
||||||
|
|
||||||
// [Api-End]
|
|
||||||
#include "../asmjit_apiend.h"
|
|
||||||
|
|
||||||
// [Guard]
|
|
||||||
#endif // !ASMJIT_DISABLE_BUIILDER
|
|
||||||
#endif // _ASMJIT_X86_X86SSETOAVXPASS_P_H
|
|
||||||
@@ -2899,7 +2899,7 @@ static void generateOpcodes(asmjit::X86Assembler& a, bool useRex1 = false, bool
|
|||||||
a.vpxor(ymmA, ymmB, anyptr_gpC);
|
a.vpxor(ymmA, ymmB, anyptr_gpC);
|
||||||
a.vpxor(ymmA, ymmB, ymmC);
|
a.vpxor(ymmA, ymmB, ymmC);
|
||||||
|
|
||||||
// FMA3.
|
// FMA.
|
||||||
a.nop();
|
a.nop();
|
||||||
|
|
||||||
a.vfmadd132pd(xmmA, xmmB, anyptr_gpC);
|
a.vfmadd132pd(xmmA, xmmB, anyptr_gpC);
|
||||||
|
|||||||
@@ -74,20 +74,22 @@ static void dumpCpu(void) {
|
|||||||
static const DumpCpuFeature x86FeaturesList[] = {
|
static const DumpCpuFeature x86FeaturesList[] = {
|
||||||
{ CpuInfo::kX86FeatureNX , "NX (Non-Execute Bit)" },
|
{ CpuInfo::kX86FeatureNX , "NX (Non-Execute Bit)" },
|
||||||
{ CpuInfo::kX86FeatureMT , "MT (Multi-Threading)" },
|
{ CpuInfo::kX86FeatureMT , "MT (Multi-Threading)" },
|
||||||
{ CpuInfo::kX86FeatureRDTSC , "RDTSC" },
|
|
||||||
{ CpuInfo::kX86FeatureRDTSCP , "RDTSCP" },
|
|
||||||
{ CpuInfo::kX86FeatureCMOV , "CMOV" },
|
{ CpuInfo::kX86FeatureCMOV , "CMOV" },
|
||||||
{ CpuInfo::kX86FeatureCMPXCHG8B , "CMPXCHG8B" },
|
{ CpuInfo::kX86FeatureCMPXCHG8B , "CMPXCHG8B" },
|
||||||
{ CpuInfo::kX86FeatureCMPXCHG16B , "CMPXCHG16B" },
|
{ CpuInfo::kX86FeatureCMPXCHG16B , "CMPXCHG16B" },
|
||||||
|
{ CpuInfo::kX86FeatureMSR , "MSR" },
|
||||||
|
{ CpuInfo::kX86FeatureRDTSC , "RDTSC" },
|
||||||
|
{ CpuInfo::kX86FeatureRDTSCP , "RDTSCP" },
|
||||||
{ CpuInfo::kX86FeatureCLFLUSH , "CLFLUSH" },
|
{ CpuInfo::kX86FeatureCLFLUSH , "CLFLUSH" },
|
||||||
{ CpuInfo::kX86FeatureCLFLUSH_OPT , "CLFLUSH_OPT" },
|
{ CpuInfo::kX86FeatureCLFLUSHOPT , "CLFLUSHOPT" },
|
||||||
{ CpuInfo::kX86FeatureCLWB , "CLWB" },
|
{ CpuInfo::kX86FeatureCLWB , "CLWB" },
|
||||||
|
{ CpuInfo::kX86FeatureCLZERO , "CLZERO" },
|
||||||
{ CpuInfo::kX86FeaturePCOMMIT , "PCOMMIT" },
|
{ CpuInfo::kX86FeaturePCOMMIT , "PCOMMIT" },
|
||||||
{ CpuInfo::kX86FeaturePREFETCH , "PREFETCH" },
|
{ CpuInfo::kX86FeaturePREFETCHW , "PREFETCHW" },
|
||||||
{ CpuInfo::kX86FeaturePREFETCHWT1 , "PREFETCHWT1" },
|
{ CpuInfo::kX86FeaturePREFETCHWT1 , "PREFETCHWT1" },
|
||||||
{ CpuInfo::kX86FeatureLAHF_SAHF , "LAHF/SAHF" },
|
{ CpuInfo::kX86FeatureLAHFSAHF , "LAHF/SAHF" },
|
||||||
{ CpuInfo::kX86FeatureFXSR , "FXSR" },
|
{ CpuInfo::kX86FeatureFXSR , "FXSR" },
|
||||||
{ CpuInfo::kX86FeatureFXSR_OPT , "FXSR_OPT" },
|
{ CpuInfo::kX86FeatureFXSROPT , "FXSROPT" },
|
||||||
{ CpuInfo::kX86FeatureMMX , "MMX" },
|
{ CpuInfo::kX86FeatureMMX , "MMX" },
|
||||||
{ CpuInfo::kX86FeatureMMX2 , "MMX2" },
|
{ CpuInfo::kX86FeatureMMX2 , "MMX2" },
|
||||||
{ CpuInfo::kX86Feature3DNOW , "3DNOW" },
|
{ CpuInfo::kX86Feature3DNOW , "3DNOW" },
|
||||||
@@ -112,11 +114,12 @@ static void dumpCpu(void) {
|
|||||||
{ CpuInfo::kX86FeatureSMEP , "SMEP" },
|
{ CpuInfo::kX86FeatureSMEP , "SMEP" },
|
||||||
{ CpuInfo::kX86FeatureSHA , "SHA" },
|
{ CpuInfo::kX86FeatureSHA , "SHA" },
|
||||||
{ CpuInfo::kX86FeatureXSAVE , "XSAVE" },
|
{ CpuInfo::kX86FeatureXSAVE , "XSAVE" },
|
||||||
{ CpuInfo::kX86FeatureXSAVE_OS , "XSAVE (OS)" },
|
{ CpuInfo::kX86FeatureXSAVEOPT , "XSAVEOPT" },
|
||||||
|
{ CpuInfo::kX86FeatureOSXSAVE , "OSXSAVE" },
|
||||||
{ CpuInfo::kX86FeatureAVX , "AVX" },
|
{ CpuInfo::kX86FeatureAVX , "AVX" },
|
||||||
{ CpuInfo::kX86FeatureAVX2 , "AVX2" },
|
{ CpuInfo::kX86FeatureAVX2 , "AVX2" },
|
||||||
{ CpuInfo::kX86FeatureF16C , "F16C" },
|
{ CpuInfo::kX86FeatureF16C , "F16C" },
|
||||||
{ CpuInfo::kX86FeatureFMA3 , "FMA3" },
|
{ CpuInfo::kX86FeatureFMA , "FMA" },
|
||||||
{ CpuInfo::kX86FeatureFMA4 , "FMA4" },
|
{ CpuInfo::kX86FeatureFMA4 , "FMA4" },
|
||||||
{ CpuInfo::kX86FeatureXOP , "XOP" },
|
{ CpuInfo::kX86FeatureXOP , "XOP" },
|
||||||
{ CpuInfo::kX86FeatureBMI , "BMI" },
|
{ CpuInfo::kX86FeatureBMI , "BMI" },
|
||||||
@@ -128,15 +131,18 @@ static void dumpCpu(void) {
|
|||||||
{ CpuInfo::kX86FeatureRTM , "RTM" },
|
{ CpuInfo::kX86FeatureRTM , "RTM" },
|
||||||
{ CpuInfo::kX86FeatureERMS , "ERMS" },
|
{ CpuInfo::kX86FeatureERMS , "ERMS" },
|
||||||
{ CpuInfo::kX86FeatureFSGSBASE , "FSGSBASE" },
|
{ CpuInfo::kX86FeatureFSGSBASE , "FSGSBASE" },
|
||||||
{ CpuInfo::kX86FeatureAVX512_F , "AVX512F" },
|
{ CpuInfo::kX86FeatureAVX512_F , "AVX512-F" },
|
||||||
{ CpuInfo::kX86FeatureAVX512_CDI , "AVX512CDI" },
|
{ CpuInfo::kX86FeatureAVX512_CDI , "AVX512-CDI" },
|
||||||
{ CpuInfo::kX86FeatureAVX512_PFI , "AVX512PFI" },
|
{ CpuInfo::kX86FeatureAVX512_PFI , "AVX512-PFI" },
|
||||||
{ CpuInfo::kX86FeatureAVX512_ERI , "AVX512ERI" },
|
{ CpuInfo::kX86FeatureAVX512_ERI , "AVX512-ERI" },
|
||||||
{ CpuInfo::kX86FeatureAVX512_DQ , "AVX512DQ" },
|
{ CpuInfo::kX86FeatureAVX512_DQ , "AVX512-DQ" },
|
||||||
{ CpuInfo::kX86FeatureAVX512_BW , "AVX512BW" },
|
{ CpuInfo::kX86FeatureAVX512_BW , "AVX512-BW" },
|
||||||
{ CpuInfo::kX86FeatureAVX512_VL , "AVX512VL" },
|
{ CpuInfo::kX86FeatureAVX512_VL , "AVX512-VL" },
|
||||||
{ CpuInfo::kX86FeatureAVX512_IFMA , "AVX512IFMA" },
|
{ CpuInfo::kX86FeatureAVX512_IFMA , "AVX512-IFMA" },
|
||||||
{ CpuInfo::kX86FeatureAVX512_VBMI , "AVX512VBMI" }
|
{ CpuInfo::kX86FeatureAVX512_VBMI , "AVX512-VBMI" },
|
||||||
|
{ CpuInfo::kX86FeatureAVX512_VPOPCNTDQ, "AVX512-VPOPCNTDQ" },
|
||||||
|
{ CpuInfo::kX86FeatureAVX512_4FMAPS , "AVX512-4FMAPS" },
|
||||||
|
{ CpuInfo::kX86FeatureAVX512_4VNNIW , "AVX512-4VNNIW" }
|
||||||
};
|
};
|
||||||
|
|
||||||
INFO("X86 Specific:");
|
INFO("X86 Specific:");
|
||||||
@@ -238,6 +244,8 @@ static void dumpSizeOf(void) {
|
|||||||
#endif // !ASMJIT_DISABLE_COMPILER
|
#endif // !ASMJIT_DISABLE_COMPILER
|
||||||
DUMP_TYPE(X86Inst);
|
DUMP_TYPE(X86Inst);
|
||||||
DUMP_TYPE(X86Inst::CommonData);
|
DUMP_TYPE(X86Inst::CommonData);
|
||||||
|
DUMP_TYPE(X86Inst::OperationData);
|
||||||
|
DUMP_TYPE(X86Inst::SseToAvxData);
|
||||||
DUMP_TYPE(X86Inst::ISignature);
|
DUMP_TYPE(X86Inst::ISignature);
|
||||||
DUMP_TYPE(X86Inst::OSignature);
|
DUMP_TYPE(X86Inst::OSignature);
|
||||||
INFO("");
|
INFO("");
|
||||||
|
|||||||
@@ -1270,7 +1270,7 @@ public:
|
|||||||
result.setFormat("ret=\"%s\"", dst);
|
result.setFormat("ret=\"%s\"", dst);
|
||||||
expect.setFormat("ret=\"%s\"", src);
|
expect.setFormat("ret=\"%s\"", src);
|
||||||
|
|
||||||
return ::memcmp(dst, src, strlen(src) + 1) == 0;
|
return result == expect;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1608,7 +1608,7 @@ public:
|
|||||||
expectBuf[4], expectBuf[5], expectBuf[6], expectBuf[7],
|
expectBuf[4], expectBuf[5], expectBuf[6], expectBuf[7],
|
||||||
expectBuf[8]);
|
expectBuf[8]);
|
||||||
|
|
||||||
return ::memcmp(resultBuf, expectBuf, 9) == 0;
|
return result == expect;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2034,7 +2034,7 @@ public:
|
|||||||
result.appendString("}");
|
result.appendString("}");
|
||||||
expect.appendString("}");
|
expect.appendString("}");
|
||||||
|
|
||||||
return ::memcmp(dstBuffer, srcBuffer, kCount * sizeof(uint32_t)) == 0;
|
return result == expect;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -2113,7 +2113,7 @@ public:
|
|||||||
result.appendString("}");
|
result.appendString("}");
|
||||||
expect.appendString("}");
|
expect.appendString("}");
|
||||||
|
|
||||||
return ::memcmp(expBuffer, dstBuffer, kCount * sizeof(uint32_t)) == 0;
|
return result == expect;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -3421,6 +3421,67 @@ public:
|
|||||||
static void ASMJIT_FASTCALL handler() { longjmp(globalJmpBuf, 1); }
|
static void ASMJIT_FASTCALL handler() { longjmp(globalJmpBuf, 1); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// [X86Test_Bug100]
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
class X86Test_Bug100 : public X86Test {
|
||||||
|
public:
|
||||||
|
X86Test_Bug100() : X86Test("[Alloc] Bug#100") {}
|
||||||
|
|
||||||
|
static void add(X86TestManager& mgr) {
|
||||||
|
mgr.add(new X86Test_Bug100());
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void compile(X86Compiler& cc) {
|
||||||
|
cc.addFunc(FuncSignature4<void, void*, uint32_t, uint32_t, uint32_t>(CallConv::kIdHost));
|
||||||
|
|
||||||
|
Label L2 = cc.newLabel();
|
||||||
|
Label L3 = cc.newLabel();
|
||||||
|
Label L4 = cc.newLabel();
|
||||||
|
|
||||||
|
X86Gp dst = cc.newIntPtr("dst");
|
||||||
|
X86Gp v0 = cc.newU32("v0");
|
||||||
|
X86Gp v1 = cc.newU32("v1");
|
||||||
|
X86Gp v2 = cc.newU32("v2");
|
||||||
|
|
||||||
|
cc.setArg(0, dst);
|
||||||
|
cc.setArg(1, v0);
|
||||||
|
cc.setArg(2, v1);
|
||||||
|
cc.setArg(3, v2);
|
||||||
|
|
||||||
|
cc.cmp(v0, 65535);
|
||||||
|
cc.jne(L2);
|
||||||
|
|
||||||
|
cc.cmp(v0, v1);
|
||||||
|
cc.je(L3);
|
||||||
|
|
||||||
|
cc.mov(v0, v2);
|
||||||
|
cc.jmp(cc.getFunc()->getExitLabel());
|
||||||
|
|
||||||
|
cc.bind(L3);
|
||||||
|
cc.bind(L4);
|
||||||
|
|
||||||
|
cc.mov(v2, v1);
|
||||||
|
cc.cmp(v1, 65535);
|
||||||
|
cc.jne(L2);
|
||||||
|
|
||||||
|
cc.mov(v0, 128);
|
||||||
|
|
||||||
|
cc.bind(L2);
|
||||||
|
cc.mov(x86::ptr(dst), v0);
|
||||||
|
|
||||||
|
cc.endFunc();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool run(void* _func, StringBuilder& result, StringBuilder& expect) {
|
||||||
|
// TODO: This test is not complete.
|
||||||
|
// typedef void (*Func)(void*, const void*, size_t);
|
||||||
|
// Func func = ptr_as_func<Func>(_func);
|
||||||
|
return result == expect;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// [CmdLine]
|
// [CmdLine]
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -3524,5 +3585,8 @@ int main(int argc, char* argv[]) {
|
|||||||
ADD_TEST(X86Test_MiscFastEval);
|
ADD_TEST(X86Test_MiscFastEval);
|
||||||
ADD_TEST(X86Test_MiscUnfollow);
|
ADD_TEST(X86Test_MiscUnfollow);
|
||||||
|
|
||||||
|
// Bugs.
|
||||||
|
ADD_TEST(X86Test_Bug100);
|
||||||
|
|
||||||
return testMgr.run();
|
return testMgr.run();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -91,16 +91,6 @@ class StringUtils {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static arrayToMap(arr, value) {
|
|
||||||
if (value === undefined)
|
|
||||||
value = true;
|
|
||||||
|
|
||||||
const map = Object.create(null);
|
|
||||||
for (var i = 0; i < arr.length; i++)
|
|
||||||
map[arr[i]] = value;
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
static makeCxxArray(array, code, indent) {
|
static makeCxxArray(array, code, indent) {
|
||||||
if (!indent) indent = kIndent;
|
if (!indent) indent = kIndent;
|
||||||
return `${code} = {\n${indent}` + array.join(`,\n${indent}`) + `\n};\n`;
|
return `${code} = {\n${indent}` + array.join(`,\n${indent}`) + `\n};\n`;
|
||||||
@@ -161,6 +151,65 @@ class StringUtils {
|
|||||||
}
|
}
|
||||||
exports.StringUtils = StringUtils;
|
exports.StringUtils = StringUtils;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// [MapUtils]
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class MapUtils {
|
||||||
|
static arrayToMap(arr, value) {
|
||||||
|
if (value === undefined)
|
||||||
|
value = true;
|
||||||
|
|
||||||
|
const map = Object.create(null);
|
||||||
|
for (var i = 0; i < arr.length; i++)
|
||||||
|
map[arr[i]] = value;
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
static equals(a, b) {
|
||||||
|
for (var k in a) if (!hasOwn.call(b, k)) return false;
|
||||||
|
for (var k in b) if (!hasOwn.call(a, k)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static firstOf(map, flags) {
|
||||||
|
for (var k in flags)
|
||||||
|
if (hasOwn.call(map, k))
|
||||||
|
return k;
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
static anyOf(map, flags) {
|
||||||
|
for (var k in flags)
|
||||||
|
if (hasOwn.call(map, k))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static add(a, b) {
|
||||||
|
for (var k in b)
|
||||||
|
a[k] = b[k];
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static and(a, b) {
|
||||||
|
const out = Object.create(null);
|
||||||
|
for (var k in a)
|
||||||
|
if (hasOwn.call(b, k))
|
||||||
|
out[k] = true;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
static xor(a, b) {
|
||||||
|
const out = Object.create(null);
|
||||||
|
for (var k in a) if (!hasOwn.call(b, k)) out[k] = true;
|
||||||
|
for (var k in b) if (!hasOwn.call(a, k)) out[k] = true;
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
exports.MapUtils = MapUtils;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// [IndexedArray]
|
// [IndexedArray]
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user