diff options
Diffstat (limited to '3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp')
-rw-r--r-- | 3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp | 465 |
1 files changed, 251 insertions, 214 deletions
diff --git a/3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp b/3rdparty/asmjit/src/asmjit/x86/x86formatter.cpp index 06553e401e0..d62dd18b638 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 +#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,67 @@ 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 }; }; @@ -120,7 +104,7 @@ struct RegFormatInfo_T { } #define ASMJIT_REG_NAME_ENTRY(TYPE) { \ - RegTraits<TYPE>::kCount, \ + RegTraits<RegType(TYPE)>::kCount, \ RegFormatInfo_T<TYPE>::kFormatIndex, \ RegFormatInfo_T<TYPE>::kSpecialIndex, \ RegFormatInfo_T<TYPE>::kSpecialCount \ @@ -146,7 +130,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 +156,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 +170,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 +197,9 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "ADX\0" "AESNI\0" "ALTMOVCR8\0" + "AMX_BF16\0" + "AMX_INT8\0" + "AMX_TILE\0" "AVX\0" "AVX2\0" "AVX512_4FMAPS\0" @@ -222,6 +211,7 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "AVX512_DQ\0" "AVX512_ERI\0" "AVX512_F\0" + "AVX512_FP16\0" "AVX512_IFMA\0" "AVX512_PFI\0" "AVX512_VBMI\0" @@ -230,8 +220,11 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "AVX512_VNNI\0" "AVX512_VP2INTERSECT\0" "AVX512_VPOPCNTDQ\0" + "AVX_VNNI\0" "BMI\0" "BMI2\0" + "CET_IBT\0" + "CET_SS\0" "CLDEMOTE\0" "CLFLUSH\0" "CLFLUSHOPT\0" @@ -253,10 +246,12 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "GEODE\0" "GFNI\0" "HLE\0" + "HRESET\0" "I486\0" "LAHFSAHF\0" "LWP\0" "LZCNT\0" + "MCOMMIT\0" "MMX\0" "MMX2\0" "MONITOR\0" @@ -268,23 +263,27 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "MSR\0" "MSSE\0" "OSXSAVE\0" + "OSPKE\0" "PCLMULQDQ\0" - "PCOMMIT\0" "PCONFIG\0" "POPCNT\0" "PREFETCHW\0" "PREFETCHWT1\0" + "PTWRITE\0" "RDPID\0" + "RDPRU\0" "RDRAND\0" "RDSEED\0" "RDTSC\0" "RDTSCP\0" "RTM\0" + "SERIALIZE\0" "SHA\0" "SKINIT\0" "SMAP\0" "SMEP\0" "SMX\0" + "SNP\0" "SSE\0" "SSE2\0" "SSE3\0" @@ -295,6 +294,8 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "SVM\0" "TBM\0" "TSX\0" + "TSXLDTRK\0" + "UINTR\0" "VAES\0" "VMX\0" "VPCLMULQDQ\0" @@ -308,32 +309,84 @@ Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept "<Unknown>\0"; static const uint16_t sFeatureIndex[] = { - 0, 5, 8, 11, 17, 24, 28, 34, 44, 48, 53, 67, 81, 93, 107, 117, 128, 138, - 149, 158, 170, 181, 193, 206, 216, 228, 248, 265, 269, 274, 283, 291, 302, - 307, 314, 319, 330, 340, 346, 353, 358, 363, 367, 372, 376, 385, 390, 398, - 404, 409, 413, 418, 427, 431, 437, 441, 446, 454, 463, 469, 479, 487, 491, - 495, 500, 508, 518, 526, 534, 541, 551, 563, 569, 576, 583, 589, 596, 600, - 604, 611, 616, 621, 625, 629, 634, 639, 646, 653, 659, 665, 669, 673, 677, - 682, 686, 697, 705, 714, 718, 724, 731, 740, 747 + 0, 5, 8, 11, 17, 24, 28, 34, 44, 53, 62, 71, 75, 80, 94, 108, 120, 134, 144, + 155, 165, 176, 185, 197, 209, 220, 232, 245, 255, 267, 287, 304, 313, 317, + 322, 330, 337, 346, 354, 365, 370, 377, 382, 393, 403, 409, 416, 421, 426, + 430, 435, 439, 448, 453, 461, 467, 472, 476, 483, 488, 497, 501, 507, 515, + 519, 524, 532, 541, 547, 557, 565, 569, 573, 578, 586, 592, 602, 610, 617, + 627, 639, 647, 653, 659, 666, 673, 679, 686, 690, 700, 704, 711, 716, 721, + 725, 729, 733, 738, 743, 750, 757, 763, 769, 773, 777, 781, 790, 796, 801, + 805, 816, 824, 833, 837, 843, 850, 859, 866 }; // @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)]); +} + +// 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)))); + + if (vReg->type() != type && uint32_t(type) <= uint32_t(RegType::kMaxValue) && Support::test(formatFlags, FormatFlags::kRegCasts)) { + 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); } -// ============================================================================ -// [asmjit::x86::FormatterInternal - Format Operand] -// ============================================================================ +// 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 +399,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 +430,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 +446,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 +461,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,15 +471,14 @@ 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 = '}'; @@ -508,12 +566,12 @@ ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmText(String& sb, uint3 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" @@ -746,106 +804,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 +881,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(arch, instId, sb)); } else { ASMJIT_PROPAGATE(sb.appendFormat("[InstId=#%u]", unsigned(instId))); @@ -868,34 +892,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>())); + 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}")); } } |