diff options
Diffstat (limited to '3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp')
-rw-r--r-- | 3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp | 583 |
1 files changed, 334 insertions, 249 deletions
diff --git a/3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp b/3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp index 06553e401e0..67b38dfa779 100644 --- a/3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp +++ b/3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp @@ -1,33 +1,16 @@ -// AsmJit - Machine code generation for C++ +// This file is part of AsmJit project <https://asmjit.com> // -// * Official AsmJit Home Page: https://asmjit.com -// * Official Github Repository: https://github.com/asmjit/asmjit -// -// Copyright (c) 2008-2020 The AsmJit Authors -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would be -// appreciated but is not required. -// 2. Altered source versions must be plainly marked as such, and must not be -// misrepresented as being the original software. -// 3. This notice may not be removed or altered from any source distribution. +// See asmjit.h or LICENSE.md for license and copyright information +// SPDX-License-Identifier: Zlib #include "../core/api-build_p.h" -#ifndef ASMJIT_NO_LOGGING +#if !defined(ASMJIT_NO_X86) && !defined(ASMJIT_NO_LOGGING) +#include "../core/cpuinfo.h" #include "../core/misc_p.h" #include "../core/support.h" -#include "../x86/x86features.h" #include "../x86/x86formatter_p.h" +#include "../x86/x86instapi_p.h" #include "../x86/x86instdb_p.h" #include "../x86/x86operand.h" @@ -37,9 +20,8 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86) -// ============================================================================ -// [asmjit::x86::FormatterInternal - Constants] -// ============================================================================ +// x86::FormatterInternal - Constants +// ================================== struct RegFormatInfo { struct TypeEntry { @@ -53,65 +35,85 @@ struct RegFormatInfo { uint8_t specialCount; }; - TypeEntry typeEntries[BaseReg::kTypeMax + 1]; + TypeEntry typeEntries[uint32_t(RegType::kMaxValue) + 1]; char typeStrings[128 - 32]; - NameEntry nameEntries[BaseReg::kTypeMax + 1]; + NameEntry nameEntries[uint32_t(RegType::kMaxValue) + 1]; char nameStrings[280]; }; template<uint32_t X> struct RegFormatInfo_T { enum { - kTypeIndex = X == Reg::kTypeGpbLo ? 1 : - X == Reg::kTypeGpbHi ? 8 : - X == Reg::kTypeGpw ? 15 : - X == Reg::kTypeGpd ? 19 : - X == Reg::kTypeGpq ? 23 : - X == Reg::kTypeXmm ? 27 : - X == Reg::kTypeYmm ? 31 : - X == Reg::kTypeZmm ? 35 : - X == Reg::kTypeMm ? 50 : - X == Reg::kTypeKReg ? 53 : - X == Reg::kTypeSReg ? 43 : - X == Reg::kTypeCReg ? 59 : - X == Reg::kTypeDReg ? 62 : - X == Reg::kTypeSt ? 47 : - X == Reg::kTypeBnd ? 55 : - X == Reg::kTypeRip ? 39 : 0, - - kFormatIndex = X == Reg::kTypeGpbLo ? 1 : - X == Reg::kTypeGpbHi ? 6 : - X == Reg::kTypeGpw ? 11 : - X == Reg::kTypeGpd ? 16 : - X == Reg::kTypeGpq ? 21 : - X == Reg::kTypeXmm ? 25 : - X == Reg::kTypeYmm ? 31 : - X == Reg::kTypeZmm ? 37 : - X == Reg::kTypeMm ? 60 : - X == Reg::kTypeKReg ? 65 : - X == Reg::kTypeSReg ? 49 : - X == Reg::kTypeCReg ? 75 : - X == Reg::kTypeDReg ? 80 : - X == Reg::kTypeSt ? 55 : - X == Reg::kTypeBnd ? 69 : - X == Reg::kTypeRip ? 43 : 0, - - kSpecialIndex = X == Reg::kTypeGpbLo ? 96 : - X == Reg::kTypeGpbHi ? 128 : - X == Reg::kTypeGpw ? 161 : - X == Reg::kTypeGpd ? 160 : - X == Reg::kTypeGpq ? 192 : - X == Reg::kTypeSReg ? 224 : - X == Reg::kTypeRip ? 85 : 0, - - kSpecialCount = X == Reg::kTypeGpbLo ? 8 : - X == Reg::kTypeGpbHi ? 4 : - X == Reg::kTypeGpw ? 8 : - X == Reg::kTypeGpd ? 8 : - X == Reg::kTypeGpq ? 8 : - X == Reg::kTypeSReg ? 7 : - X == Reg::kTypeRip ? 1 : 0 + kTypeIndex = X == uint32_t(RegType::kX86_GpbLo) ? 1 : + X == uint32_t(RegType::kX86_GpbHi) ? 8 : + X == uint32_t(RegType::kX86_Gpw ) ? 15 : + X == uint32_t(RegType::kX86_Gpd ) ? 19 : + X == uint32_t(RegType::kX86_Gpq ) ? 23 : + X == uint32_t(RegType::kX86_Xmm ) ? 27 : + X == uint32_t(RegType::kX86_Ymm ) ? 31 : + X == uint32_t(RegType::kX86_Zmm ) ? 35 : + X == uint32_t(RegType::kX86_Mm ) ? 50 : + X == uint32_t(RegType::kX86_KReg ) ? 53 : + X == uint32_t(RegType::kX86_SReg ) ? 43 : + X == uint32_t(RegType::kX86_CReg ) ? 59 : + X == uint32_t(RegType::kX86_DReg ) ? 62 : + X == uint32_t(RegType::kX86_St ) ? 47 : + X == uint32_t(RegType::kX86_Bnd ) ? 55 : + X == uint32_t(RegType::kX86_Tmm ) ? 65 : + X == uint32_t(RegType::kX86_Rip ) ? 39 : 0, + + kFormatIndex = X == uint32_t(RegType::kX86_GpbLo) ? 1 : + X == uint32_t(RegType::kX86_GpbHi) ? 6 : + X == uint32_t(RegType::kX86_Gpw ) ? 11 : + X == uint32_t(RegType::kX86_Gpd ) ? 16 : + X == uint32_t(RegType::kX86_Gpq ) ? 21 : + X == uint32_t(RegType::kX86_Xmm ) ? 25 : + X == uint32_t(RegType::kX86_Ymm ) ? 31 : + X == uint32_t(RegType::kX86_Zmm ) ? 37 : + X == uint32_t(RegType::kX86_Mm ) ? 60 : + X == uint32_t(RegType::kX86_KReg ) ? 65 : + X == uint32_t(RegType::kX86_SReg ) ? 49 : + X == uint32_t(RegType::kX86_CReg ) ? 75 : + X == uint32_t(RegType::kX86_DReg ) ? 80 : + X == uint32_t(RegType::kX86_St ) ? 55 : + X == uint32_t(RegType::kX86_Bnd ) ? 69 : + X == uint32_t(RegType::kX86_Tmm ) ? 89 : + X == uint32_t(RegType::kX86_Rip ) ? 43 : 0, + + kSpecialIndex = X == uint32_t(RegType::kX86_GpbLo) ? 96 : + X == uint32_t(RegType::kX86_GpbHi) ? 128 : + X == uint32_t(RegType::kX86_Gpw ) ? 161 : + X == uint32_t(RegType::kX86_Gpd ) ? 160 : + X == uint32_t(RegType::kX86_Gpq ) ? 192 : + X == uint32_t(RegType::kX86_SReg ) ? 224 : + X == uint32_t(RegType::kX86_Rip ) ? 85 : 0, + + kSpecialCount = X == uint32_t(RegType::kX86_GpbLo) ? 8 : + X == uint32_t(RegType::kX86_GpbHi) ? 4 : + X == uint32_t(RegType::kX86_Gpw ) ? 8 : + X == uint32_t(RegType::kX86_Gpd ) ? 8 : + X == uint32_t(RegType::kX86_Gpq ) ? 8 : + X == uint32_t(RegType::kX86_SReg ) ? 7 : + X == uint32_t(RegType::kX86_Rip ) ? 1 : 0, + + kRegCount = X == uint32_t(RegType::kX86_GpbLo) ? 32 : + X == uint32_t(RegType::kX86_GpbHi) ? 4 : + X == uint32_t(RegType::kX86_Gpw ) ? 32 : + X == uint32_t(RegType::kX86_Gpd ) ? 32 : + X == uint32_t(RegType::kX86_Gpq ) ? 32 : + X == uint32_t(RegType::kX86_Xmm ) ? 32 : + X == uint32_t(RegType::kX86_Ymm ) ? 32 : + X == uint32_t(RegType::kX86_Zmm ) ? 32 : + X == uint32_t(RegType::kX86_Mm ) ? 8 : + X == uint32_t(RegType::kX86_KReg ) ? 8 : + X == uint32_t(RegType::kX86_SReg ) ? 7 : + X == uint32_t(RegType::kX86_CReg ) ? 16 : + X == uint32_t(RegType::kX86_DReg ) ? 16 : + X == uint32_t(RegType::kX86_St ) ? 8 : + X == uint32_t(RegType::kX86_Bnd ) ? 4 : + X == uint32_t(RegType::kX86_Tmm ) ? 8 : + X == uint32_t(RegType::kX86_Rip ) ? 1 : 0 }; }; @@ -120,7 +122,7 @@ struct RegFormatInfo_T { } #define ASMJIT_REG_NAME_ENTRY(TYPE) { \ - RegTraits<TYPE>::kCount, \ + RegFormatInfo_T<TYPE>::kRegCount, \ RegFormatInfo_T<TYPE>::kFormatIndex, \ RegFormatInfo_T<TYPE>::kSpecialIndex, \ RegFormatInfo_T<TYPE>::kSpecialCount \ @@ -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 @@ -183,25 +188,24 @@ static const RegFormatInfo x86RegFormatInfo = { static const char* x86GetAddressSizeString(uint32_t size) noexcept { switch (size) { - case 1 : return "byte "; - case 2 : return "word "; - case 4 : return "dword "; - case 6 : return "fword "; - case 8 : return "qword "; - case 10: return "tword "; - case 16: return "oword "; - case 32: return "yword "; - case 64: return "zword "; + case 1 : return "byte ptr "; + case 2 : return "word ptr "; + case 4 : return "dword ptr "; + case 6 : return "fword ptr "; + case 8 : return "qword ptr "; + case 10: return "tbyte ptr "; + case 16: return "xmmword ptr "; + case 32: return "ymmword ptr "; + case 64: return "zmmword ptr "; default: return ""; } } -// ============================================================================ -// [asmjit::x86::FormatterInternal - Format Feature] -// ============================================================================ +// x86::FormatterInternal - Format FeatureId +// ========================================= Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept { - // @EnumStringBegin{"enum": "x86::Features::Id", "output": "sFeature", "strip": "k"}@ + // @EnumStringBegin{"enum": "CpuFeatures::X86", "output": "sFeature", "strip": "k"}@ static const char sFeatureString[] = "None\0" "MT\0" @@ -211,6 +215,12 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "ADX\0" "AESNI\0" "ALTMOVCR8\0" + "AMX_BF16\0" + "AMX_COMPLEX\0" + "AMX_FP16\0" + "AMX_INT8\0" + "AMX_TILE\0" + "APX_F\0" "AVX\0" "AVX2\0" "AVX512_4FMAPS\0" @@ -218,26 +228,36 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "AVX512_BF16\0" "AVX512_BITALG\0" "AVX512_BW\0" - "AVX512_CDI\0" + "AVX512_CD\0" "AVX512_DQ\0" - "AVX512_ERI\0" + "AVX512_ER\0" "AVX512_F\0" + "AVX512_FP16\0" "AVX512_IFMA\0" - "AVX512_PFI\0" + "AVX512_PF\0" "AVX512_VBMI\0" "AVX512_VBMI2\0" "AVX512_VL\0" "AVX512_VNNI\0" "AVX512_VP2INTERSECT\0" "AVX512_VPOPCNTDQ\0" + "AVX_IFMA\0" + "AVX_NE_CONVERT\0" + "AVX_VNNI\0" + "AVX_VNNI_INT16\0" + "AVX_VNNI_INT8\0" "BMI\0" "BMI2\0" + "CET_IBT\0" + "CET_SS\0" + "CET_SSS\0" "CLDEMOTE\0" "CLFLUSH\0" "CLFLUSHOPT\0" "CLWB\0" "CLZERO\0" "CMOV\0" + "CMPCCXADD\0" "CMPXCHG16B\0" "CMPXCHG8B\0" "ENCLV\0" @@ -248,15 +268,23 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "FMA4\0" "FPU\0" "FSGSBASE\0" + "FSRM\0" + "FSRC\0" + "FSRS\0" "FXSR\0" "FXSROPT\0" + "FZRM\0" "GEODE\0" "GFNI\0" "HLE\0" + "HRESET\0" "I486\0" + "INVLPGB\0" "LAHFSAHF\0" + "LAM\0" "LWP\0" "LZCNT\0" + "MCOMMIT\0" "MMX\0" "MMX2\0" "MONITOR\0" @@ -266,23 +294,38 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "MOVDIRI\0" "MPX\0" "MSR\0" + "MSRLIST\0" "MSSE\0" "OSXSAVE\0" + "OSPKE\0" "PCLMULQDQ\0" - "PCOMMIT\0" "PCONFIG\0" "POPCNT\0" + "PREFETCHI\0" "PREFETCHW\0" "PREFETCHWT1\0" + "PTWRITE\0" + "RAO_INT\0" + "RMPQUERY\0" "RDPID\0" + "RDPRU\0" "RDRAND\0" "RDSEED\0" "RDTSC\0" "RDTSCP\0" "RTM\0" + "SEAM\0" + "SERIALIZE\0" + "SEV\0" + "SEV_ES\0" + "SEV_SNP\0" "SHA\0" + "SHA512\0" "SKINIT\0" + "SM3\0" + "SM4\0" "SMAP\0" + "SME\0" "SMEP\0" "SMX\0" "SSE\0" @@ -294,12 +337,16 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "SSSE3\0" "SVM\0" "TBM\0" + "TSE\0" "TSX\0" + "TSXLDTRK\0" + "UINTR\0" "VAES\0" "VMX\0" "VPCLMULQDQ\0" "WAITPKG\0" "WBNOINVD\0" + "WRMSRNS\0" "XOP\0" "XSAVE\0" "XSAVEC\0" @@ -308,32 +355,89 @@ 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, 65, 74, 83, 92, 98, 102, 107, 121, 135, + 147, 161, 171, 181, 191, 201, 210, 222, 234, 244, 256, 269, 279, 291, 311, + 328, 337, 352, 361, 376, 390, 394, 399, 407, 414, 422, 431, 439, 450, 455, + 462, 467, 477, 488, 498, 504, 511, 516, 521, 525, 530, 534, 543, 548, 553, + 558, 563, 571, 576, 582, 587, 591, 598, 603, 611, 620, 624, 628, 634, 642, + 646, 651, 659, 668, 674, 684, 692, 696, 700, 708, 713, 721, 727, 737, 745, + 752, 762, 772, 784, 792, 800, 809, 815, 821, 828, 835, 841, 848, 852, 857, + 867, 871, 878, 886, 890, 897, 904, 908, 912, 917, 921, 926, 930, 934, 939, + 944, 951, 958, 964, 970, 974, 978, 982, 986, 995, 1001, 1006, 1010, 1021, + 1029, 1038, 1046, 1050, 1056, 1063, 1072, 1079 }; // @EnumStringEnd@ - return sb.append(sFeatureString + sFeatureIndex[Support::min<uint32_t>(featureId, x86::Features::kCount)]); + return sb.append(sFeatureString + sFeatureIndex[Support::min<uint32_t>(featureId, uint32_t(CpuFeatures::X86::kMaxValue) + 1)]); } -// ============================================================================ -// [asmjit::x86::FormatterInternal - Format Operand] -// ============================================================================ +// x86::FormatterInternal - Format Register +// ======================================== + +ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister(String& sb, FormatFlags formatFlags, const BaseEmitter* emitter, Arch arch, RegType type, uint32_t id) noexcept { + DebugUtils::unused(arch); + const RegFormatInfo& info = x86RegFormatInfo; + +#ifndef ASMJIT_NO_COMPILER + if (Operand::isVirtId(id)) { + if (emitter && emitter->emitterType() == EmitterType::kCompiler) { + const BaseCompiler* cc = static_cast<const BaseCompiler*>(emitter); + if (cc->isVirtIdValid(id)) { + VirtReg* vReg = cc->virtRegById(id); + ASMJIT_ASSERT(vReg != nullptr); + + const char* name = vReg->name(); + if (name && name[0] != '\0') + ASMJIT_PROPAGATE(sb.append(name)); + else + ASMJIT_PROPAGATE(sb.appendFormat("%%%u", unsigned(Operand::virtIdToIndex(id)))); + + bool formatType = (Support::test(formatFlags, FormatFlags::kRegType)) || + (Support::test(formatFlags, FormatFlags::kRegCasts) && vReg->type() != type); + + if (formatType && uint32_t(type) <= uint32_t(RegType::kMaxValue)) { + const RegFormatInfo::TypeEntry& typeEntry = info.typeEntries[size_t(type)]; + if (typeEntry.index) + ASMJIT_PROPAGATE(sb.appendFormat("@%s", info.typeStrings + typeEntry.index)); + } + + return kErrorOk; + } + } + } +#else + DebugUtils::unused(emitter, formatFlags); +#endif + + if (uint32_t(type) <= uint32_t(RegType::kMaxValue)) { + const RegFormatInfo::NameEntry& nameEntry = info.nameEntries[size_t(type)]; + + if (id < nameEntry.specialCount) + return sb.append(info.nameStrings + nameEntry.specialIndex + id * 4); + + if (id < nameEntry.count) + return sb.appendFormat(info.nameStrings + nameEntry.formatIndex, unsigned(id)); + + const RegFormatInfo::TypeEntry& typeEntry = info.typeEntries[size_t(type)]; + if (typeEntry.index) + return sb.appendFormat("%s@%u", info.typeStrings + typeEntry.index, id); + } + + return sb.appendFormat("<Reg-%u>?%u", uint32_t(type), id); +} + +// x86::FormatterInternal - Format Operand +// ======================================= ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( String& sb, - uint32_t flags, + FormatFlags formatFlags, const BaseEmitter* emitter, - uint32_t arch, + Arch arch, const Operand_& op) noexcept { if (op.isReg()) - return formatRegister(sb, flags, emitter, arch, op.as<BaseReg>().type(), op.as<BaseReg>().id()); + return formatRegister(sb, formatFlags, emitter, arch, op.as<BaseReg>().type(), op.as<BaseReg>().id()); if (op.isMem()) { const Mem& m = op.as<Mem>(); @@ -346,21 +450,27 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( ASMJIT_PROPAGATE(sb.append('[')); switch (m.addrType()) { - case BaseMem::kAddrTypeAbs: ASMJIT_PROPAGATE(sb.append("abs ")); break; - case BaseMem::kAddrTypeRel: ASMJIT_PROPAGATE(sb.append("rel ")); break; + case Mem::AddrType::kDefault: + break; + case Mem::AddrType::kAbs: + ASMJIT_PROPAGATE(sb.append("abs ")); + break; + case Mem::AddrType::kRel: + ASMJIT_PROPAGATE(sb.append("rel ")); + break; } char opSign = '\0'; if (m.hasBase()) { opSign = '+'; if (m.hasBaseLabel()) { - ASMJIT_PROPAGATE(Formatter::formatLabel(sb, flags, emitter, m.baseId())); + ASMJIT_PROPAGATE(Formatter::formatLabel(sb, formatFlags, emitter, m.baseId())); } else { - uint32_t modifiedFlags = flags; + FormatFlags modifiedFlags = formatFlags; if (m.isRegHome()) { ASMJIT_PROPAGATE(sb.append("&")); - modifiedFlags &= ~FormatOptions::kFlagRegCasts; + modifiedFlags &= ~FormatFlags::kRegCasts; } ASMJIT_PROPAGATE(formatRegister(sb, modifiedFlags, emitter, arch, m.baseType(), m.baseId())); } @@ -371,7 +481,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( ASMJIT_PROPAGATE(sb.append(opSign)); opSign = '+'; - ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, m.indexType(), m.indexId())); + ASMJIT_PROPAGATE(formatRegister(sb, formatFlags, emitter, arch, m.indexType(), m.indexId())); if (m.hasShift()) ASMJIT_PROPAGATE(sb.appendFormat("*%u", 1 << m.shift())); } @@ -387,7 +497,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( ASMJIT_PROPAGATE(sb.append(opSign)); uint32_t base = 10; - if ((flags & FormatOptions::kFlagHexOffsets) != 0 && off > 9) { + if (Support::test(formatFlags, FormatFlags::kHexOffsets) && off > 9) { ASMJIT_PROPAGATE(sb.append("0x", 2)); base = 16; } @@ -402,7 +512,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( const Imm& i = op.as<Imm>(); int64_t val = i.value(); - if ((flags & FormatOptions::kFlagHexImms) != 0 && uint64_t(val) > 9) { + if (Support::test(formatFlags, FormatFlags::kHexImms) && uint64_t(val) > 9) { ASMJIT_PROPAGATE(sb.append("0x", 2)); return sb.appendUInt(uint64_t(val), 16); } @@ -412,19 +522,18 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand( } if (op.isLabel()) { - return Formatter::formatLabel(sb, flags, emitter, op.id()); + return Formatter::formatLabel(sb, formatFlags, emitter, op.id()); } return sb.append("<None>"); } -// ============================================================================ -// [asmjit::x86::FormatterInternal - Format Immediate (Extension)] -// ============================================================================ +// x86::FormatterInternal - Format Immediate (Extension) +// ===================================================== static constexpr char kImmCharStart = '{'; -static constexpr char kImmCharEnd = '}'; -static constexpr char kImmCharOr = '|'; +static constexpr char kImmCharEnd = '}'; +static constexpr char kImmCharOr = '|'; struct ImmBits { enum Mode : uint32_t { @@ -438,29 +547,29 @@ struct ImmBits { char text[48 - 3]; }; -ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmShuf(String& sb, uint32_t u8, uint32_t bits, uint32_t count) noexcept { +ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmShuf(String& sb, uint32_t imm8, uint32_t bits, uint32_t count) noexcept { uint32_t mask = (1 << bits) - 1; + uint32_t lastPredicateShift = bits * (count - 1u); - for (uint32_t i = 0; i < count; i++, u8 >>= bits) { - uint32_t value = u8 & mask; + for (uint32_t i = 0; i < count; i++, imm8 <<= bits) { + uint32_t index = (imm8 >> lastPredicateShift) & mask; ASMJIT_PROPAGATE(sb.append(i == 0 ? kImmCharStart : kImmCharOr)); - ASMJIT_PROPAGATE(sb.appendUInt(value)); + ASMJIT_PROPAGATE(sb.appendUInt(index)); } - if (kImmCharEnd) - ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); + ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); return kErrorOk; } -ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmBits(String& sb, uint32_t u8, const ImmBits* bits, uint32_t count) noexcept { +ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmBits(String& sb, uint32_t imm8, const ImmBits* bits, uint32_t count) noexcept { uint32_t n = 0; char buf[64]; for (uint32_t i = 0; i < count; i++) { const ImmBits& spec = bits[i]; - uint32_t value = (u8 & uint32_t(spec.mask)) >> spec.shift; + uint32_t value = (imm8 & uint32_t(spec.mask)) >> spec.shift; const char* str = nullptr; switch (spec.mode) { @@ -484,36 +593,33 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmBits(String& sb, uint3 ASMJIT_PROPAGATE(sb.append(str)); } - if (n && kImmCharEnd) + if (n) ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); return kErrorOk; } -ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmText(String& sb, uint32_t u8, uint32_t bits, uint32_t advance, const char* text, uint32_t count = 1) noexcept { +ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmText(String& sb, uint32_t imm8, uint32_t bits, uint32_t advance, const char* text, uint32_t count = 1) noexcept { uint32_t mask = (1u << bits) - 1; uint32_t pos = 0; - for (uint32_t i = 0; i < count; i++, u8 >>= bits, pos += advance) { - uint32_t value = (u8 & mask) + pos; + for (uint32_t i = 0; i < count; i++, imm8 >>= bits, pos += advance) { + uint32_t value = (imm8 & mask) + pos; ASMJIT_PROPAGATE(sb.append(i == 0 ? kImmCharStart : kImmCharOr)); ASMJIT_PROPAGATE(sb.append(Support::findPackedString(text, value))); } - if (kImmCharEnd) - ASMJIT_PROPAGATE(sb.append(kImmCharEnd)); - - return kErrorOk; + return sb.append(kImmCharEnd); } ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst( String& sb, - uint32_t flags, - uint32_t instId, + FormatFlags formatFlags, + InstId instId, uint32_t vecSize, const Imm& imm) noexcept { - DebugUtils::unused(flags); + DebugUtils::unused(formatFlags); static const char vcmpx[] = "EQ_OQ\0" "LT_OS\0" "LE_OS\0" "UNORD_Q\0" "NEQ_UQ\0" "NLT_US\0" "NLE_US\0" "ORD_Q\0" @@ -525,8 +631,8 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst( static const char vpcmpx[] = "EQ\0" "LT\0" "LE\0" "FALSE\0" "NEQ\0" "GE\0" "GT\0" "TRUE\0"; static const char vpcomx[] = "LT\0" "LE\0" "GT\0" "GE\0" "EQ\0" "NEQ\0" "FALSE\0" "TRUE\0"; - static const char vshufpd[] = "A0\0A1\0B0\0B1\0A2\0A3\0B2\0B3\0A4\0A5\0B4\0B5\0A6\0A7\0B6\0B7\0"; - static const char vshufps[] = "A0\0A1\0A2\0A3\0A0\0A1\0A2\0A3\0B0\0B1\0B2\0B3\0B0\0B1\0B2\0B3\0"; + static const char vshufpd[] = "A0\0" "A1\0" "B0\0" "B1\0" "A2\0" "A3\0" "B2\0" "B3\0" "A4\0" "A5\0" "B4\0" "B5\0" "A6\0" "A7\0" "B6\0" "B7\0"; + static const char vshufps[] = "A0\0" "A1\0" "A2\0" "A3\0" "A0\0" "A1\0" "A2\0" "A3\0" "B0\0" "B1\0" "B2\0" "B3\0" "B0\0" "B1\0" "B2\0" "B3\0"; static const ImmBits vfpclassxx[] = { { 0x07u, 0, ImmBits::kModeLookup, "QNAN\0" "+0\0" "-0\0" "+INF\0" "-INF\0" "DENORMAL\0" "-FINITE\0" "SNAN\0" } @@ -550,25 +656,25 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst( }; static const ImmBits vmpsadbw[] = { - { 0x04u, 2, ImmBits::kModeLookup, "BLK1[0]\0" "BLK1[1]\0" }, - { 0x03u, 0, ImmBits::kModeLookup, "BLK2[0]\0" "BLK2[1]\0" "BLK2[2]\0" "BLK2[3]\0" }, { 0x40u, 6, ImmBits::kModeLookup, "BLK1[4]\0" "BLK1[5]\0" }, - { 0x30u, 4, ImmBits::kModeLookup, "BLK2[4]\0" "BLK2[5]\0" "BLK2[6]\0" "BLK2[7]\0" } + { 0x30u, 4, ImmBits::kModeLookup, "BLK2[4]\0" "BLK2[5]\0" "BLK2[6]\0" "BLK2[7]\0" }, + { 0x04u, 2, ImmBits::kModeLookup, "BLK1[0]\0" "BLK1[1]\0" }, + { 0x03u, 0, ImmBits::kModeLookup, "BLK2[0]\0" "BLK2[1]\0" "BLK2[2]\0" "BLK2[3]\0" } }; static const ImmBits vpclmulqdq[] = { - { 0x01u, 0, ImmBits::kModeLookup, "LQ\0" "HQ\0" }, - { 0x10u, 4, ImmBits::kModeLookup, "LQ\0" "HQ\0" } + { 0x10u, 4, ImmBits::kModeLookup, "LQ\0" "HQ\0" }, + { 0x01u, 0, ImmBits::kModeLookup, "LQ\0" "HQ\0" } }; static const ImmBits vperm2x128[] = { - { 0x0Bu, 0, ImmBits::kModeLookup, "A0\0" "A1\0" "B0\0" "B1\0" "\0" "\0" "\0" "\0" "0\0" "0\0" "0\0" "0\0" }, - { 0xB0u, 4, ImmBits::kModeLookup, "A0\0" "A1\0" "B0\0" "B1\0" "\0" "\0" "\0" "\0" "0\0" "0\0" "0\0" "0\0" } + { 0xB0u, 4, ImmBits::kModeLookup, "A0\0" "A1\0" "B0\0" "B1\0" "\0" "\0" "\0" "\0" "0\0" "0\0" "0\0" "0\0" }, + { 0x0Bu, 0, ImmBits::kModeLookup, "A0\0" "A1\0" "B0\0" "B1\0" "\0" "\0" "\0" "\0" "0\0" "0\0" "0\0" "0\0" } }; static const ImmBits vrangexx[] = { - { 0x03u, 0, ImmBits::kModeLookup, "MIN\0" "MAX\0" "MIN_ABS\0" "MAX_ABS\0" }, - { 0x0Cu, 2, ImmBits::kModeLookup, "SIGN_A\0" "SIGN_B\0" "SIGN_0\0" "SIGN_1\0" } + { 0x0Cu, 2, ImmBits::kModeLookup, "SIGN_A\0" "SIGN_B\0" "SIGN_0\0" "SIGN_1\0" }, + { 0x03u, 0, ImmBits::kModeLookup, "MIN\0" "MAX\0" "MIN_ABS\0" "MAX_ABS\0" } }; static const ImmBits vreducexx_vrndscalexx[] = { @@ -746,106 +852,76 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst( } } -// ============================================================================ -// [asmjit::x86::FormatterInternal - Format Register] -// ============================================================================ - -ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister(String& sb, uint32_t flags, const BaseEmitter* emitter, uint32_t arch, uint32_t rType, uint32_t rId) noexcept { - DebugUtils::unused(arch); - const RegFormatInfo& info = x86RegFormatInfo; - -#ifndef ASMJIT_NO_COMPILER - if (Operand::isVirtId(rId)) { - if (emitter && emitter->emitterType() == BaseEmitter::kTypeCompiler) { - const BaseCompiler* cc = static_cast<const BaseCompiler*>(emitter); - if (cc->isVirtIdValid(rId)) { - VirtReg* vReg = cc->virtRegById(rId); - ASMJIT_ASSERT(vReg != nullptr); - - const char* name = vReg->name(); - if (name && name[0] != '\0') - ASMJIT_PROPAGATE(sb.append(name)); - else - ASMJIT_PROPAGATE(sb.appendFormat("%%%u", unsigned(Operand::virtIdToIndex(rId)))); - - if (vReg->type() != rType && rType <= BaseReg::kTypeMax && (flags & FormatOptions::kFlagRegCasts) != 0) { - const RegFormatInfo::TypeEntry& typeEntry = info.typeEntries[rType]; - if (typeEntry.index) - ASMJIT_PROPAGATE(sb.appendFormat("@%s", info.typeStrings + typeEntry.index)); - } - - return kErrorOk; - } - } - } -#else - DebugUtils::unused(emitter, flags); -#endif - - if (ASMJIT_LIKELY(rType <= BaseReg::kTypeMax)) { - const RegFormatInfo::NameEntry& nameEntry = info.nameEntries[rType]; - - if (rId < nameEntry.specialCount) - return sb.append(info.nameStrings + nameEntry.specialIndex + rId * 4); - - if (rId < nameEntry.count) - return sb.appendFormat(info.nameStrings + nameEntry.formatIndex, unsigned(rId)); - - const RegFormatInfo::TypeEntry& typeEntry = info.typeEntries[rType]; - if (typeEntry.index) - return sb.appendFormat("%s@%u", info.typeStrings + typeEntry.index, rId); - } - - return sb.appendFormat("Reg?%u@%u", rType, rId); -} - -// ============================================================================ -// [asmjit::x86::FormatterInternal - Format Instruction] -// ============================================================================ +// x86::FormatterInternal - Format Instruction +// =========================================== ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( String& sb, - uint32_t flags, + FormatFlags formatFlags, const BaseEmitter* emitter, - uint32_t arch, + Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept { - uint32_t instId = inst.id(); - uint32_t options = inst.options(); + InstId instId = inst.id(); + InstOptions options = inst.options(); // Format instruction options and instruction mnemonic. if (instId < Inst::_kIdCount) { + // VEX|EVEX options. + if (Support::test(options, InstOptions::kX86_Vex)) + ASMJIT_PROPAGATE(sb.append("{vex} ")); + + if (Support::test(options, InstOptions::kX86_Vex3)) + ASMJIT_PROPAGATE(sb.append("{vex3} ")); + + if (Support::test(options, InstOptions::kX86_Evex)) + ASMJIT_PROPAGATE(sb.append("{evex} ")); + + // MOD/RM and MOD/MR options + if (Support::test(options, InstOptions::kX86_ModRM)) + ASMJIT_PROPAGATE(sb.append("{modrm} ")); + else if (Support::test(options, InstOptions::kX86_ModMR)) + ASMJIT_PROPAGATE(sb.append("{modmr} ")); + // SHORT|LONG options. - if (options & Inst::kOptionShortForm) ASMJIT_PROPAGATE(sb.append("short ")); - if (options & Inst::kOptionLongForm) ASMJIT_PROPAGATE(sb.append("long ")); + if (Support::test(options, InstOptions::kShortForm)) + ASMJIT_PROPAGATE(sb.append("short ")); + + if (Support::test(options, InstOptions::kLongForm)) + ASMJIT_PROPAGATE(sb.append("long ")); // LOCK|XACQUIRE|XRELEASE options. - if (options & Inst::kOptionXAcquire) ASMJIT_PROPAGATE(sb.append("xacquire ")); - if (options & Inst::kOptionXRelease) ASMJIT_PROPAGATE(sb.append("xrelease ")); - if (options & Inst::kOptionLock) ASMJIT_PROPAGATE(sb.append("lock ")); + if (Support::test(options, InstOptions::kX86_XAcquire)) + ASMJIT_PROPAGATE(sb.append("xacquire ")); + + if (Support::test(options, InstOptions::kX86_XRelease)) + ASMJIT_PROPAGATE(sb.append("xrelease ")); + + if (Support::test(options, InstOptions::kX86_Lock)) + ASMJIT_PROPAGATE(sb.append("lock ")); // REP|REPNE options. - if (options & (Inst::kOptionRep | Inst::kOptionRepne)) { - sb.append((options & Inst::kOptionRep) ? "rep " : "repnz "); + if (Support::test(options, InstOptions::kX86_Rep | InstOptions::kX86_Repne)) { + sb.append(Support::test(options, InstOptions::kX86_Rep) ? "rep " : "repnz "); if (inst.hasExtraReg()) { ASMJIT_PROPAGATE(sb.append("{")); - ASMJIT_PROPAGATE(formatOperand(sb, flags, emitter, arch, inst.extraReg().toReg<BaseReg>())); + ASMJIT_PROPAGATE(formatOperand(sb, formatFlags, emitter, arch, inst.extraReg().toReg<BaseReg>())); ASMJIT_PROPAGATE(sb.append("} ")); } } // REX options. - if (options & Inst::kOptionRex) { - const uint32_t kRXBWMask = Inst::kOptionOpCodeR | - Inst::kOptionOpCodeX | - Inst::kOptionOpCodeB | - Inst::kOptionOpCodeW ; - if (options & kRXBWMask) { - sb.append("rex."); - if (options & Inst::kOptionOpCodeR) sb.append('r'); - if (options & Inst::kOptionOpCodeX) sb.append('x'); - if (options & Inst::kOptionOpCodeB) sb.append('b'); - if (options & Inst::kOptionOpCodeW) sb.append('w'); + if (Support::test(options, InstOptions::kX86_Rex)) { + const InstOptions kRXBWMask = InstOptions::kX86_OpCodeR | + InstOptions::kX86_OpCodeX | + InstOptions::kX86_OpCodeB | + InstOptions::kX86_OpCodeW ; + if (Support::test(options, kRXBWMask)) { + ASMJIT_PROPAGATE(sb.append("rex.")); + if (Support::test(options, InstOptions::kX86_OpCodeR)) sb.append('r'); + if (Support::test(options, InstOptions::kX86_OpCodeX)) sb.append('x'); + if (Support::test(options, InstOptions::kX86_OpCodeB)) sb.append('b'); + if (Support::test(options, InstOptions::kX86_OpCodeW)) sb.append('w'); sb.append(' '); } else { @@ -853,11 +929,7 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( } } - // VEX|EVEX options. - if (options & Inst::kOptionVex3) ASMJIT_PROPAGATE(sb.append("vex3 ")); - if (options & Inst::kOptionEvex) ASMJIT_PROPAGATE(sb.append("evex ")); - - ASMJIT_PROPAGATE(InstAPI::instIdToString(arch, instId, sb)); + ASMJIT_PROPAGATE(InstInternal::instIdToString(instId, sb)); } else { ASMJIT_PROPAGATE(sb.appendFormat("[InstId=#%u]", unsigned(instId))); @@ -868,34 +940,47 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( if (op.isNone()) break; ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", ")); - ASMJIT_PROPAGATE(formatOperand(sb, flags, emitter, arch, op)); + ASMJIT_PROPAGATE(formatOperand(sb, formatFlags, emitter, arch, op)); - if (op.isImm() && (flags & FormatOptions::kFlagExplainImms)) { + if (op.isImm() && uint32_t(formatFlags & FormatFlags::kExplainImms)) { uint32_t vecSize = 16; for (uint32_t j = 0; j < opCount; j++) if (operands[j].isReg()) - vecSize = Support::max<uint32_t>(vecSize, operands[j].size()); - ASMJIT_PROPAGATE(FormatterInternal_explainConst(sb, flags, instId, vecSize, op.as<Imm>())); + vecSize = Support::max<uint32_t>(vecSize, operands[j].as<Reg>().size()); + ASMJIT_PROPAGATE(FormatterInternal_explainConst(sb, formatFlags, instId, vecSize, op.as<Imm>())); } // Support AVX-512 masking - {k}{z}. if (i == 0) { - if (inst.extraReg().group() == Reg::kGroupKReg) { + if (inst.extraReg().group() == RegGroup::kX86_K) { ASMJIT_PROPAGATE(sb.append(" {")); - ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, inst.extraReg().type(), inst.extraReg().id())); + ASMJIT_PROPAGATE(formatRegister(sb, formatFlags, emitter, arch, inst.extraReg().type(), inst.extraReg().id())); ASMJIT_PROPAGATE(sb.append('}')); - if (options & Inst::kOptionZMask) + if (Support::test(options, InstOptions::kX86_ZMask)) ASMJIT_PROPAGATE(sb.append("{z}")); } - else if (options & Inst::kOptionZMask) { + else if (Support::test(options, InstOptions::kX86_ZMask)) { ASMJIT_PROPAGATE(sb.append(" {z}")); } } // Support AVX-512 broadcast - {1tox}. if (op.isMem() && op.as<Mem>().hasBroadcast()) { - ASMJIT_PROPAGATE(sb.appendFormat(" {1to%u}", Support::bitMask(op.as<Mem>().getBroadcast()))); + ASMJIT_PROPAGATE(sb.appendFormat(" {1to%u}", Support::bitMask(uint32_t(op.as<Mem>().getBroadcast())))); + } + } + + // Support AVX-512 embedded rounding and suppress-all-exceptions {sae}. + if (inst.hasOption(InstOptions::kX86_ER | InstOptions::kX86_SAE)) { + if (inst.hasOption(InstOptions::kX86_ER)) { + uint32_t bits = uint32_t(inst.options() & InstOptions::kX86_ERMask) >> Support::ConstCTZ<uint32_t(InstOptions::kX86_ERMask)>::value; + + const char roundingModes[] = "rn\0rd\0ru\0rz"; + ASMJIT_PROPAGATE(sb.appendFormat(", {%s-sae}", roundingModes + bits * 3)); + } + else { + ASMJIT_PROPAGATE(sb.append(", {sae}")); } } @@ -904,4 +989,4 @@ ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction( ASMJIT_END_SUB_NAMESPACE -#endif // !ASMJIT_NO_LOGGING +#endif // !ASMJIT_NO_X86 && !ASMJIT_NO_LOGGING |