LCOV - code coverage report
Current view: top level - asmjit - x86formatter.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 0 235 0.0 %
Date: 2026-11-05 10:19:06 Functions: 0 9 0.0 %

          Line data    Source code
       1             : #ifdef __PLUMED_HAS_ASMJIT
       2             : // This file is part of AsmJit project <https://asmjit.com>
       3             : //
       4             : // See asmjit.h or LICENSE.md for license and copyright information
       5             : // SPDX-License-Identifier: Zlib
       6             : 
       7             : #include "api-build_p.h"
       8             : #ifndef ASMJIT_NO_LOGGING
       9             : 
      10             : #include "cpuinfo.h"
      11             : #include "misc_p.h"
      12             : #include "support.h"
      13             : #include "x86formatter_p.h"
      14             : #include "x86instapi_p.h"
      15             : #include "x86instdb_p.h"
      16             : #include "x86operand.h"
      17             : 
      18             : #ifndef ASMJIT_NO_COMPILER
      19             :   #include "compiler.h"
      20             : #endif
      21             : 
      22             : ASMJIT_BEGIN_SUB_NAMESPACE(x86)
      23             : 
      24             : // x86::FormatterInternal - Constants
      25             : // ==================================
      26             : 
      27             : struct RegFormatInfo {
      28             :   struct TypeEntry {
      29             :     uint8_t index;
      30             :   };
      31             : 
      32             :   struct NameEntry {
      33             :     uint8_t count;
      34             :     uint8_t formatIndex;
      35             :     uint8_t specialIndex;
      36             :     uint8_t specialCount;
      37             :   };
      38             : 
      39             :   TypeEntry typeEntries[uint32_t(RegType::kMaxValue) + 1];
      40             :   char typeStrings[128 - 32];
      41             : 
      42             :   NameEntry nameEntries[uint32_t(RegType::kMaxValue) + 1];
      43             :   char nameStrings[280];
      44             : };
      45             : 
      46             : template<uint32_t X>
      47             : struct RegFormatInfo_T {
      48             :   enum {
      49             :     kTypeIndex    = X == uint32_t(RegType::kX86_GpbLo) ? 1   :
      50             :                     X == uint32_t(RegType::kX86_GpbHi) ? 8   :
      51             :                     X == uint32_t(RegType::kX86_Gpw  ) ? 15  :
      52             :                     X == uint32_t(RegType::kX86_Gpd  ) ? 19  :
      53             :                     X == uint32_t(RegType::kX86_Gpq  ) ? 23  :
      54             :                     X == uint32_t(RegType::kX86_Xmm  ) ? 27  :
      55             :                     X == uint32_t(RegType::kX86_Ymm  ) ? 31  :
      56             :                     X == uint32_t(RegType::kX86_Zmm  ) ? 35  :
      57             :                     X == uint32_t(RegType::kX86_Mm   ) ? 50  :
      58             :                     X == uint32_t(RegType::kX86_KReg ) ? 53  :
      59             :                     X == uint32_t(RegType::kX86_SReg ) ? 43  :
      60             :                     X == uint32_t(RegType::kX86_CReg ) ? 59  :
      61             :                     X == uint32_t(RegType::kX86_DReg ) ? 62  :
      62             :                     X == uint32_t(RegType::kX86_St   ) ? 47  :
      63             :                     X == uint32_t(RegType::kX86_Bnd  ) ? 55  :
      64             :                     X == uint32_t(RegType::kX86_Tmm  ) ? 65  :
      65             :                     X == uint32_t(RegType::kX86_Rip  ) ? 39  : 0,
      66             : 
      67             :     kFormatIndex  = X == uint32_t(RegType::kX86_GpbLo) ? 1   :
      68             :                     X == uint32_t(RegType::kX86_GpbHi) ? 6   :
      69             :                     X == uint32_t(RegType::kX86_Gpw  ) ? 11  :
      70             :                     X == uint32_t(RegType::kX86_Gpd  ) ? 16  :
      71             :                     X == uint32_t(RegType::kX86_Gpq  ) ? 21  :
      72             :                     X == uint32_t(RegType::kX86_Xmm  ) ? 25  :
      73             :                     X == uint32_t(RegType::kX86_Ymm  ) ? 31  :
      74             :                     X == uint32_t(RegType::kX86_Zmm  ) ? 37  :
      75             :                     X == uint32_t(RegType::kX86_Mm   ) ? 60  :
      76             :                     X == uint32_t(RegType::kX86_KReg ) ? 65  :
      77             :                     X == uint32_t(RegType::kX86_SReg ) ? 49  :
      78             :                     X == uint32_t(RegType::kX86_CReg ) ? 75  :
      79             :                     X == uint32_t(RegType::kX86_DReg ) ? 80  :
      80             :                     X == uint32_t(RegType::kX86_St   ) ? 55  :
      81             :                     X == uint32_t(RegType::kX86_Bnd  ) ? 69  :
      82             :                     X == uint32_t(RegType::kX86_Tmm  ) ? 89  :
      83             :                     X == uint32_t(RegType::kX86_Rip  ) ? 43  : 0,
      84             : 
      85             :     kSpecialIndex = X == uint32_t(RegType::kX86_GpbLo) ? 96  :
      86             :                     X == uint32_t(RegType::kX86_GpbHi) ? 128 :
      87             :                     X == uint32_t(RegType::kX86_Gpw  ) ? 161 :
      88             :                     X == uint32_t(RegType::kX86_Gpd  ) ? 160 :
      89             :                     X == uint32_t(RegType::kX86_Gpq  ) ? 192 :
      90             :                     X == uint32_t(RegType::kX86_SReg ) ? 224 :
      91             :                     X == uint32_t(RegType::kX86_Rip  ) ? 85  : 0,
      92             : 
      93             :     kSpecialCount = X == uint32_t(RegType::kX86_GpbLo) ? 8   :
      94             :                     X == uint32_t(RegType::kX86_GpbHi) ? 4   :
      95             :                     X == uint32_t(RegType::kX86_Gpw  ) ? 8   :
      96             :                     X == uint32_t(RegType::kX86_Gpd  ) ? 8   :
      97             :                     X == uint32_t(RegType::kX86_Gpq  ) ? 8   :
      98             :                     X == uint32_t(RegType::kX86_SReg ) ? 7   :
      99             :                     X == uint32_t(RegType::kX86_Rip  ) ? 1   : 0
     100             :   };
     101             : };
     102             : 
     103             : #define ASMJIT_REG_TYPE_ENTRY(TYPE) {   \
     104             :   RegFormatInfo_T<TYPE>::kTypeIndex     \
     105             : }
     106             : 
     107             : #define ASMJIT_REG_NAME_ENTRY(TYPE) {   \
     108             :   RegTraits<RegType(TYPE)>::kCount,     \
     109             :   RegFormatInfo_T<TYPE>::kFormatIndex,  \
     110             :   RegFormatInfo_T<TYPE>::kSpecialIndex, \
     111             :   RegFormatInfo_T<TYPE>::kSpecialCount  \
     112             : }
     113             : 
     114             : static const RegFormatInfo x86RegFormatInfo = {
     115             :   // Register type entries and strings.
     116             :   { ASMJIT_LOOKUP_TABLE_32(ASMJIT_REG_TYPE_ENTRY, 0) },
     117             : 
     118             :   "\0"             // #0
     119             :   "gpb\0\0\0\0"    // #1
     120             :   "gpb.hi\0"       // #8
     121             :   "gpw\0"          // #15
     122             :   "gpd\0"          // #19
     123             :   "gpq\0"          // #23
     124             :   "xmm\0"          // #27
     125             :   "ymm\0"          // #31
     126             :   "zmm\0"          // #35
     127             :   "rip\0"          // #39
     128             :   "seg\0"          // #43
     129             :   "st\0"           // #47
     130             :   "mm\0"           // #50
     131             :   "k\0"            // #53
     132             :   "bnd\0"          // #55
     133             :   "cr\0"           // #59
     134             :   "dr\0"           // #62
     135             :   "tmm\0"          // #65
     136             :   ,
     137             : 
     138             :   // Register name entries and strings.
     139             :   { ASMJIT_LOOKUP_TABLE_32(ASMJIT_REG_NAME_ENTRY, 0) },
     140             : 
     141             :   "\0"
     142             :   "r%ub\0"         // #1
     143             :   "r%uh\0"         // #6
     144             :   "r%uw\0"         // #11
     145             :   "r%ud\0"         // #16
     146             :   "r%u\0"          // #21
     147             :   "xmm%u\0"        // #25
     148             :   "ymm%u\0"        // #31
     149             :   "zmm%u\0"        // #37
     150             :   "rip%u\0"        // #43
     151             :   "seg%u\0"        // #49
     152             :   "st%u\0"         // #55
     153             :   "mm%u\0"         // #60
     154             :   "k%u\0"          // #65
     155             :   "bnd%u\0"        // #69
     156             :   "cr%u\0"         // #75
     157             :   "dr%u\0"         // #80
     158             : 
     159             :   "rip\0"          // #85
     160             :   "tmm%u\0"        // #89
     161             :   "\0"             // #95
     162             : 
     163             :   "al\0\0" "cl\0\0" "dl\0\0" "bl\0\0" "spl\0"  "bpl\0"  "sil\0"  "dil\0" // #96
     164             :   "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
     165             :   "eax\0"  "ecx\0"  "edx\0"  "ebx\0"  "esp\0"  "ebp\0"  "esi\0"  "edi\0" // #160
     166             :   "rax\0"  "rcx\0"  "rdx\0"  "rbx\0"  "rsp\0"  "rbp\0"  "rsi\0"  "rdi\0" // #192
     167             :   "n/a\0"  "es\0\0" "cs\0\0" "ss\0\0" "ds\0\0" "fs\0\0" "gs\0\0" "n/a\0" // #224
     168             : };
     169             : #undef ASMJIT_REG_NAME_ENTRY
     170             : #undef ASMJIT_REG_TYPE_ENTRY
     171             : 
     172           0 : static const char* x86GetAddressSizeString(uint32_t size) noexcept {
     173           0 :   switch (size) {
     174             :     case 1 : return "byte ptr ";
     175           0 :     case 2 : return "word ptr ";
     176           0 :     case 4 : return "dword ptr ";
     177           0 :     case 6 : return "fword ptr ";
     178           0 :     case 8 : return "qword ptr ";
     179           0 :     case 10: return "tbyte ptr ";
     180           0 :     case 16: return "xmmword ptr ";
     181           0 :     case 32: return "ymmword ptr ";
     182           0 :     case 64: return "zmmword ptr ";
     183           0 :     default: return "";
     184             :   }
     185             : }
     186             : 
     187             : // x86::FormatterInternal - Format FeatureId
     188             : // =========================================
     189             : 
     190           0 : Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept {
     191             :   // @EnumStringBegin{"enum": "CpuFeatures::X86", "output": "sFeature", "strip": "k"}@
     192             :   static const char sFeatureString[] =
     193             :     "None\0"
     194             :     "MT\0"
     195             :     "NX\0"
     196             :     "3DNOW\0"
     197             :     "3DNOW2\0"
     198             :     "ADX\0"
     199             :     "AESNI\0"
     200             :     "ALTMOVCR8\0"
     201             :     "AMX_BF16\0"
     202             :     "AMX_INT8\0"
     203             :     "AMX_TILE\0"
     204             :     "AVX\0"
     205             :     "AVX2\0"
     206             :     "AVX512_4FMAPS\0"
     207             :     "AVX512_4VNNIW\0"
     208             :     "AVX512_BF16\0"
     209             :     "AVX512_BITALG\0"
     210             :     "AVX512_BW\0"
     211             :     "AVX512_CDI\0"
     212             :     "AVX512_DQ\0"
     213             :     "AVX512_ERI\0"
     214             :     "AVX512_F\0"
     215             :     "AVX512_FP16\0"
     216             :     "AVX512_IFMA\0"
     217             :     "AVX512_PFI\0"
     218             :     "AVX512_VBMI\0"
     219             :     "AVX512_VBMI2\0"
     220             :     "AVX512_VL\0"
     221             :     "AVX512_VNNI\0"
     222             :     "AVX512_VP2INTERSECT\0"
     223             :     "AVX512_VPOPCNTDQ\0"
     224             :     "AVX_VNNI\0"
     225             :     "BMI\0"
     226             :     "BMI2\0"
     227             :     "CET_IBT\0"
     228             :     "CET_SS\0"
     229             :     "CLDEMOTE\0"
     230             :     "CLFLUSH\0"
     231             :     "CLFLUSHOPT\0"
     232             :     "CLWB\0"
     233             :     "CLZERO\0"
     234             :     "CMOV\0"
     235             :     "CMPXCHG16B\0"
     236             :     "CMPXCHG8B\0"
     237             :     "ENCLV\0"
     238             :     "ENQCMD\0"
     239             :     "ERMS\0"
     240             :     "F16C\0"
     241             :     "FMA\0"
     242             :     "FMA4\0"
     243             :     "FPU\0"
     244             :     "FSGSBASE\0"
     245             :     "FXSR\0"
     246             :     "FXSROPT\0"
     247             :     "GEODE\0"
     248             :     "GFNI\0"
     249             :     "HLE\0"
     250             :     "HRESET\0"
     251             :     "I486\0"
     252             :     "LAHFSAHF\0"
     253             :     "LWP\0"
     254             :     "LZCNT\0"
     255             :     "MCOMMIT\0"
     256             :     "MMX\0"
     257             :     "MMX2\0"
     258             :     "MONITOR\0"
     259             :     "MONITORX\0"
     260             :     "MOVBE\0"
     261             :     "MOVDIR64B\0"
     262             :     "MOVDIRI\0"
     263             :     "MPX\0"
     264             :     "MSR\0"
     265             :     "MSSE\0"
     266             :     "OSXSAVE\0"
     267             :     "OSPKE\0"
     268             :     "PCLMULQDQ\0"
     269             :     "PCONFIG\0"
     270             :     "POPCNT\0"
     271             :     "PREFETCHW\0"
     272             :     "PREFETCHWT1\0"
     273             :     "PTWRITE\0"
     274             :     "RDPID\0"
     275             :     "RDPRU\0"
     276             :     "RDRAND\0"
     277             :     "RDSEED\0"
     278             :     "RDTSC\0"
     279             :     "RDTSCP\0"
     280             :     "RTM\0"
     281             :     "SERIALIZE\0"
     282             :     "SHA\0"
     283             :     "SKINIT\0"
     284             :     "SMAP\0"
     285             :     "SMEP\0"
     286             :     "SMX\0"
     287             :     "SNP\0"
     288             :     "SSE\0"
     289             :     "SSE2\0"
     290             :     "SSE3\0"
     291             :     "SSE4_1\0"
     292             :     "SSE4_2\0"
     293             :     "SSE4A\0"
     294             :     "SSSE3\0"
     295             :     "SVM\0"
     296             :     "TBM\0"
     297             :     "TSX\0"
     298             :     "TSXLDTRK\0"
     299             :     "UINTR\0"
     300             :     "VAES\0"
     301             :     "VMX\0"
     302             :     "VPCLMULQDQ\0"
     303             :     "WAITPKG\0"
     304             :     "WBNOINVD\0"
     305             :     "XOP\0"
     306             :     "XSAVE\0"
     307             :     "XSAVEC\0"
     308             :     "XSAVEOPT\0"
     309             :     "XSAVES\0"
     310             :     "<Unknown>\0";
     311             : 
     312             :   static const uint16_t sFeatureIndex[] = {
     313             :     0, 5, 8, 11, 17, 24, 28, 34, 44, 53, 62, 71, 75, 80, 94, 108, 120, 134, 144,
     314             :     155, 165, 176, 185, 197, 209, 220, 232, 245, 255, 267, 287, 304, 313, 317,
     315             :     322, 330, 337, 346, 354, 365, 370, 377, 382, 393, 403, 409, 416, 421, 426,
     316             :     430, 435, 439, 448, 453, 461, 467, 472, 476, 483, 488, 497, 501, 507, 515,
     317             :     519, 524, 532, 541, 547, 557, 565, 569, 573, 578, 586, 592, 602, 610, 617,
     318             :     627, 639, 647, 653, 659, 666, 673, 679, 686, 690, 700, 704, 711, 716, 721,
     319             :     725, 729, 733, 738, 743, 750, 757, 763, 769, 773, 777, 781, 790, 796, 801,
     320             :     805, 816, 824, 833, 837, 843, 850, 859, 866
     321             :   };
     322             :   // @EnumStringEnd@
     323             : 
     324           0 :   return sb.append(sFeatureString + sFeatureIndex[Support::min<uint32_t>(featureId, uint32_t(CpuFeatures::X86::kMaxValue) + 1)]);
     325             : }
     326             : 
     327             : // x86::FormatterInternal - Format Register
     328             : // ========================================
     329             : 
     330           0 : ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister(String& sb, FormatFlags formatFlags, const BaseEmitter* emitter, Arch arch, RegType type, uint32_t id) noexcept {
     331             :   DebugUtils::unused(arch);
     332             :   const RegFormatInfo& info = x86RegFormatInfo;
     333             : 
     334             : #ifndef ASMJIT_NO_COMPILER
     335           0 :   if (Operand::isVirtId(id)) {
     336           0 :     if (emitter && emitter->emitterType() == EmitterType::kCompiler) {
     337             :       const BaseCompiler* cc = static_cast<const BaseCompiler*>(emitter);
     338           0 :       if (cc->isVirtIdValid(id)) {
     339           0 :         VirtReg* vReg = cc->virtRegById(id);
     340             :         ASMJIT_ASSERT(vReg != nullptr);
     341             : 
     342             :         const char* name = vReg->name();
     343           0 :         if (name && name[0] != '\0')
     344           0 :           ASMJIT_PROPAGATE(sb.append(name));
     345             :         else
     346           0 :           ASMJIT_PROPAGATE(sb.appendFormat("%%%u", unsigned(Operand::virtIdToIndex(id))));
     347             : 
     348           0 :         if (vReg->type() != type && uint32_t(type) <= uint32_t(RegType::kMaxValue) && Support::test(formatFlags, FormatFlags::kRegCasts)) {
     349           0 :           const RegFormatInfo::TypeEntry& typeEntry = info.typeEntries[size_t(type)];
     350           0 :           if (typeEntry.index)
     351           0 :             ASMJIT_PROPAGATE(sb.appendFormat("@%s", info.typeStrings + typeEntry.index));
     352             :         }
     353             : 
     354           0 :         return kErrorOk;
     355             :       }
     356             :     }
     357             :   }
     358             : #else
     359             :   DebugUtils::unused(emitter, formatFlags);
     360             : #endif
     361             : 
     362           0 :   if (uint32_t(type) <= uint32_t(RegType::kMaxValue)) {
     363           0 :     const RegFormatInfo::NameEntry& nameEntry = info.nameEntries[size_t(type)];
     364             : 
     365           0 :     if (id < nameEntry.specialCount)
     366           0 :       return sb.append(info.nameStrings + nameEntry.specialIndex + id * 4);
     367             : 
     368           0 :     if (id < nameEntry.count)
     369           0 :       return sb.appendFormat(info.nameStrings + nameEntry.formatIndex, unsigned(id));
     370             : 
     371             :     const RegFormatInfo::TypeEntry& typeEntry = info.typeEntries[size_t(type)];
     372           0 :     if (typeEntry.index)
     373           0 :       return sb.appendFormat("%s@%u", info.typeStrings + typeEntry.index, id);
     374             :   }
     375             : 
     376           0 :   return sb.appendFormat("<Reg-%u>?%u", uint32_t(type), id);
     377             : }
     378             : 
     379             : // x86::FormatterInternal - Format Operand
     380             : // =======================================
     381             : 
     382           0 : ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand(
     383             :   String& sb,
     384             :   FormatFlags formatFlags,
     385             :   const BaseEmitter* emitter,
     386             :   Arch arch,
     387             :   const Operand_& op) noexcept {
     388             : 
     389           0 :   if (op.isReg())
     390           0 :     return formatRegister(sb, formatFlags, emitter, arch, op.as<BaseReg>().type(), op.as<BaseReg>().id());
     391             : 
     392           0 :   if (op.isMem()) {
     393             :     const Mem& m = op.as<Mem>();
     394           0 :     ASMJIT_PROPAGATE(sb.append(x86GetAddressSizeString(m.size())));
     395             : 
     396             :     // Segment override prefix.
     397             :     uint32_t seg = m.segmentId();
     398           0 :     if (seg != SReg::kIdNone && seg < SReg::kIdCount)
     399           0 :       ASMJIT_PROPAGATE(sb.appendFormat("%s:", x86RegFormatInfo.nameStrings + 224 + size_t(seg) * 4));
     400             : 
     401           0 :     ASMJIT_PROPAGATE(sb.append('['));
     402           0 :     switch (m.addrType()) {
     403             :       case Mem::AddrType::kDefault:
     404             :         break;
     405           0 :       case Mem::AddrType::kAbs:
     406           0 :         ASMJIT_PROPAGATE(sb.append("abs "));
     407             :         break;
     408           0 :       case Mem::AddrType::kRel:
     409           0 :         ASMJIT_PROPAGATE(sb.append("rel "));
     410             :         break;
     411             :     }
     412             : 
     413             :     char opSign = '\0';
     414           0 :     if (m.hasBase()) {
     415             :       opSign = '+';
     416           0 :       if (m.hasBaseLabel()) {
     417           0 :         ASMJIT_PROPAGATE(Formatter::formatLabel(sb, formatFlags, emitter, m.baseId()));
     418             :       }
     419             :       else {
     420             :         FormatFlags modifiedFlags = formatFlags;
     421           0 :         if (m.isRegHome()) {
     422           0 :           ASMJIT_PROPAGATE(sb.append("&"));
     423             :           modifiedFlags &= ~FormatFlags::kRegCasts;
     424             :         }
     425           0 :         ASMJIT_PROPAGATE(formatRegister(sb, modifiedFlags, emitter, arch, m.baseType(), m.baseId()));
     426             :       }
     427             :     }
     428             : 
     429           0 :     if (m.hasIndex()) {
     430           0 :       if (opSign)
     431           0 :         ASMJIT_PROPAGATE(sb.append(opSign));
     432             : 
     433             :       opSign = '+';
     434           0 :       ASMJIT_PROPAGATE(formatRegister(sb, formatFlags, emitter, arch, m.indexType(), m.indexId()));
     435           0 :       if (m.hasShift())
     436           0 :         ASMJIT_PROPAGATE(sb.appendFormat("*%u", 1 << m.shift()));
     437             :     }
     438             : 
     439           0 :     uint64_t off = uint64_t(m.offset());
     440           0 :     if (off || !m.hasBaseOrIndex()) {
     441           0 :       if (int64_t(off) < 0) {
     442             :         opSign = '-';
     443           0 :         off = ~off + 1;
     444             :       }
     445             : 
     446           0 :       if (opSign)
     447           0 :         ASMJIT_PROPAGATE(sb.append(opSign));
     448             : 
     449             :       uint32_t base = 10;
     450           0 :       if (Support::test(formatFlags, FormatFlags::kHexOffsets) && off > 9) {
     451           0 :         ASMJIT_PROPAGATE(sb.append("0x", 2));
     452             :         base = 16;
     453             :       }
     454             : 
     455           0 :       ASMJIT_PROPAGATE(sb.appendUInt(off, base));
     456             :     }
     457             : 
     458           0 :     return sb.append(']');
     459             :   }
     460             : 
     461           0 :   if (op.isImm()) {
     462             :     const Imm& i = op.as<Imm>();
     463             :     int64_t val = i.value();
     464             : 
     465           0 :     if (Support::test(formatFlags, FormatFlags::kHexImms) && uint64_t(val) > 9) {
     466           0 :       ASMJIT_PROPAGATE(sb.append("0x", 2));
     467           0 :       return sb.appendUInt(uint64_t(val), 16);
     468             :     }
     469             :     else {
     470           0 :       return sb.appendInt(val, 10);
     471             :     }
     472             :   }
     473             : 
     474           0 :   if (op.isLabel()) {
     475           0 :     return Formatter::formatLabel(sb, formatFlags, emitter, op.id());
     476             :   }
     477             : 
     478           0 :   return sb.append("<None>");
     479             : }
     480             : 
     481             : // x86::FormatterInternal - Format Immediate (Extension)
     482             : // =====================================================
     483             : 
     484             : static constexpr char kImmCharStart = '{';
     485             : static constexpr char kImmCharEnd   = '}';
     486             : static constexpr char kImmCharOr    = '|';
     487             : 
     488             : struct ImmBits {
     489             :   enum Mode : uint32_t {
     490             :     kModeLookup = 0,
     491             :     kModeFormat = 1
     492             :   };
     493             : 
     494             :   uint8_t mask;
     495             :   uint8_t shift;
     496             :   uint8_t mode;
     497             :   char text[48 - 3];
     498             : };
     499             : 
     500           0 : ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmShuf(String& sb, uint32_t u8, uint32_t bits, uint32_t count) noexcept {
     501           0 :   uint32_t mask = (1 << bits) - 1;
     502             : 
     503           0 :   for (uint32_t i = 0; i < count; i++, u8 >>= bits) {
     504           0 :     uint32_t value = u8 & mask;
     505           0 :     ASMJIT_PROPAGATE(sb.append(i == 0 ? kImmCharStart : kImmCharOr));
     506           0 :     ASMJIT_PROPAGATE(sb.appendUInt(value));
     507             :   }
     508             : 
     509             :   if (kImmCharEnd)
     510           0 :     ASMJIT_PROPAGATE(sb.append(kImmCharEnd));
     511             : 
     512             :   return kErrorOk;
     513             : }
     514             : 
     515           0 : ASMJIT_FAVOR_SIZE static Error FormatterInternal_formatImmBits(String& sb, uint32_t u8, const ImmBits* bits, uint32_t count) noexcept {
     516             :   uint32_t n = 0;
     517             :   char buf[64];
     518             : 
     519           0 :   for (uint32_t i = 0; i < count; i++) {
     520           0 :     const ImmBits& spec = bits[i];
     521             : 
     522           0 :     uint32_t value = (u8 & uint32_t(spec.mask)) >> spec.shift;
     523             :     const char* str = nullptr;
     524             : 
     525           0 :     switch (spec.mode) {
     526           0 :       case ImmBits::kModeLookup:
     527           0 :         str = Support::findPackedString(spec.text, value);
     528             :         break;
     529             : 
     530           0 :       case ImmBits::kModeFormat:
     531           0 :         snprintf(buf, sizeof(buf), spec.text, unsigned(value));
     532             :         str = buf;
     533           0 :         break;
     534             : 
     535             :       default:
     536             :         return DebugUtils::errored(kErrorInvalidState);
     537             :     }
     538             : 
     539           0 :     if (!str[0])
     540           0 :       continue;
     541             : 
     542           0 :     ASMJIT_PROPAGATE(sb.append(++n == 1 ? kImmCharStart : kImmCharOr));
     543           0 :     ASMJIT_PROPAGATE(sb.append(str));
     544             :   }
     545             : 
     546           0 :   if (n && kImmCharEnd)
     547           0 :     ASMJIT_PROPAGATE(sb.append(kImmCharEnd));
     548             : 
     549             :   return kErrorOk;
     550             : }
     551             : 
     552           0 : 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 {
     553             :   uint32_t mask = (1u << bits) - 1;
     554             :   uint32_t pos = 0;
     555             : 
     556           0 :   for (uint32_t i = 0; i < count; i++, u8 >>= bits, pos += advance) {
     557           0 :     uint32_t value = (u8 & mask) + pos;
     558           0 :     ASMJIT_PROPAGATE(sb.append(i == 0 ? kImmCharStart : kImmCharOr));
     559           0 :     ASMJIT_PROPAGATE(sb.append(Support::findPackedString(text, value)));
     560             :   }
     561             : 
     562             :   if (kImmCharEnd)
     563           0 :     ASMJIT_PROPAGATE(sb.append(kImmCharEnd));
     564             : 
     565             :   return kErrorOk;
     566             : }
     567             : 
     568           0 : ASMJIT_FAVOR_SIZE static Error FormatterInternal_explainConst(
     569             :   String& sb,
     570             :   FormatFlags formatFlags,
     571             :   InstId instId,
     572             :   uint32_t vecSize,
     573             :   const Imm& imm) noexcept {
     574             : 
     575             :   DebugUtils::unused(formatFlags);
     576             : 
     577             :   static const char vcmpx[] =
     578             :     "EQ_OQ\0" "LT_OS\0"  "LE_OS\0"  "UNORD_Q\0"  "NEQ_UQ\0" "NLT_US\0" "NLE_US\0" "ORD_Q\0"
     579             :     "EQ_UQ\0" "NGE_US\0" "NGT_US\0" "FALSE_OQ\0" "NEQ_OQ\0" "GE_OS\0"  "GT_OS\0"  "TRUE_UQ\0"
     580             :     "EQ_OS\0" "LT_OQ\0"  "LE_OQ\0"  "UNORD_S\0"  "NEQ_US\0" "NLT_UQ\0" "NLE_UQ\0" "ORD_S\0"
     581             :     "EQ_US\0" "NGE_UQ\0" "NGT_UQ\0" "FALSE_OS\0" "NEQ_OS\0" "GE_OQ\0"  "GT_OQ\0"  "TRUE_US\0";
     582             : 
     583             :   // Why to make it compatible...
     584             :   static const char vpcmpx[] = "EQ\0" "LT\0" "LE\0" "FALSE\0" "NEQ\0" "GE\0"  "GT\0"    "TRUE\0";
     585             :   static const char vpcomx[] = "LT\0" "LE\0" "GT\0" "GE\0"    "EQ\0"  "NEQ\0" "FALSE\0" "TRUE\0";
     586             : 
     587             :   static const char vshufpd[] = "A0\0A1\0B0\0B1\0A2\0A3\0B2\0B3\0A4\0A5\0B4\0B5\0A6\0A7\0B6\0B7\0";
     588             :   static const char vshufps[] = "A0\0A1\0A2\0A3\0A0\0A1\0A2\0A3\0B0\0B1\0B2\0B3\0B0\0B1\0B2\0B3\0";
     589             : 
     590             :   static const ImmBits vfpclassxx[] = {
     591             :     { 0x07u, 0, ImmBits::kModeLookup, "QNAN\0" "+0\0" "-0\0" "+INF\0" "-INF\0" "DENORMAL\0" "-FINITE\0" "SNAN\0" }
     592             :   };
     593             : 
     594             :   static const ImmBits vfixupimmxx[] = {
     595             :     { 0x01u, 0, ImmBits::kModeLookup, "\0" "+INF_IE\0" },
     596             :     { 0x02u, 1, ImmBits::kModeLookup, "\0" "-VE_IE\0"  },
     597             :     { 0x04u, 2, ImmBits::kModeLookup, "\0" "-INF_IE\0" },
     598             :     { 0x08u, 3, ImmBits::kModeLookup, "\0" "SNAN_IE\0" },
     599             :     { 0x10u, 4, ImmBits::kModeLookup, "\0" "ONE_IE\0"  },
     600             :     { 0x20u, 5, ImmBits::kModeLookup, "\0" "ONE_ZE\0"  },
     601             :     { 0x40u, 6, ImmBits::kModeLookup, "\0" "ZERO_IE\0" },
     602             :     { 0x80u, 7, ImmBits::kModeLookup, "\0" "ZERO_ZE\0" }
     603             :   };
     604             : 
     605             :   static const ImmBits vgetmantxx[] = {
     606             :     { 0x03u, 0, ImmBits::kModeLookup, "[1, 2)\0" "[.5, 2)\0" "[.5, 1)\0" "[.75, 1.5)\0" },
     607             :     { 0x04u, 2, ImmBits::kModeLookup, "\0" "NO_SIGN\0" },
     608             :     { 0x08u, 3, ImmBits::kModeLookup, "\0" "QNAN_IF_SIGN\0" }
     609             :   };
     610             : 
     611             :   static const ImmBits vmpsadbw[] = {
     612             :     { 0x04u, 2, ImmBits::kModeLookup, "BLK1[0]\0" "BLK1[1]\0" },
     613             :     { 0x03u, 0, ImmBits::kModeLookup, "BLK2[0]\0" "BLK2[1]\0" "BLK2[2]\0" "BLK2[3]\0" },
     614             :     { 0x40u, 6, ImmBits::kModeLookup, "BLK1[4]\0" "BLK1[5]\0" },
     615             :     { 0x30u, 4, ImmBits::kModeLookup, "BLK2[4]\0" "BLK2[5]\0" "BLK2[6]\0" "BLK2[7]\0" }
     616             :   };
     617             : 
     618             :   static const ImmBits vpclmulqdq[] = {
     619             :     { 0x01u, 0, ImmBits::kModeLookup, "LQ\0" "HQ\0" },
     620             :     { 0x10u, 4, ImmBits::kModeLookup, "LQ\0" "HQ\0" }
     621             :   };
     622             : 
     623             :   static const ImmBits vperm2x128[] = {
     624             :     { 0x0Bu, 0, ImmBits::kModeLookup, "A0\0" "A1\0" "B0\0" "B1\0" "\0" "\0" "\0" "\0" "0\0" "0\0" "0\0" "0\0" },
     625             :     { 0xB0u, 4, ImmBits::kModeLookup, "A0\0" "A1\0" "B0\0" "B1\0" "\0" "\0" "\0" "\0" "0\0" "0\0" "0\0" "0\0" }
     626             :   };
     627             : 
     628             :   static const ImmBits vrangexx[] = {
     629             :     { 0x03u, 0, ImmBits::kModeLookup, "MIN\0" "MAX\0" "MIN_ABS\0" "MAX_ABS\0" },
     630             :     { 0x0Cu, 2, ImmBits::kModeLookup, "SIGN_A\0" "SIGN_B\0" "SIGN_0\0" "SIGN_1\0" }
     631             :   };
     632             : 
     633             :   static const ImmBits vreducexx_vrndscalexx[] = {
     634             :     { 0x07u, 0, ImmBits::kModeLookup, "\0" "\0" "\0" "\0" "ROUND\0" "FLOOR\0" "CEIL\0" "TRUNC\0" },
     635             :     { 0x08u, 3, ImmBits::kModeLookup, "\0" "SAE\0" },
     636             :     { 0xF0u, 4, ImmBits::kModeFormat, "LEN=%d" }
     637             :   };
     638             : 
     639             :   static const ImmBits vroundxx[] = {
     640             :     { 0x07u, 0, ImmBits::kModeLookup, "ROUND\0" "FLOOR\0" "CEIL\0" "TRUNC\0" "\0" "\0" "\0" "\0" },
     641             :     { 0x08u, 3, ImmBits::kModeLookup, "\0" "INEXACT\0" }
     642             :   };
     643             : 
     644           0 :   uint32_t u8 = imm.valueAs<uint8_t>();
     645           0 :   switch (instId) {
     646           0 :     case Inst::kIdVblendpd:
     647             :     case Inst::kIdBlendpd:
     648           0 :       return FormatterInternal_formatImmShuf(sb, u8, 1, vecSize / 8);
     649             : 
     650           0 :     case Inst::kIdVblendps:
     651             :     case Inst::kIdBlendps:
     652           0 :       return FormatterInternal_formatImmShuf(sb, u8, 1, vecSize / 4);
     653             : 
     654           0 :     case Inst::kIdVcmppd:
     655             :     case Inst::kIdVcmpps:
     656             :     case Inst::kIdVcmpsd:
     657             :     case Inst::kIdVcmpss:
     658           0 :       return FormatterInternal_formatImmText(sb, u8, 5, 0, vcmpx);
     659             : 
     660           0 :     case Inst::kIdCmppd:
     661             :     case Inst::kIdCmpps:
     662             :     case Inst::kIdCmpsd:
     663             :     case Inst::kIdCmpss:
     664           0 :       return FormatterInternal_formatImmText(sb, u8, 3, 0, vcmpx);
     665             : 
     666           0 :     case Inst::kIdVdbpsadbw:
     667           0 :       return FormatterInternal_formatImmShuf(sb, u8, 2, 4);
     668             : 
     669           0 :     case Inst::kIdVdppd:
     670             :     case Inst::kIdVdpps:
     671             :     case Inst::kIdDppd:
     672             :     case Inst::kIdDpps:
     673           0 :       return FormatterInternal_formatImmShuf(sb, u8, 1, 8);
     674             : 
     675           0 :     case Inst::kIdVmpsadbw:
     676             :     case Inst::kIdMpsadbw:
     677           0 :       return FormatterInternal_formatImmBits(sb, u8, vmpsadbw, Support::min<uint32_t>(vecSize / 8, 4));
     678             : 
     679           0 :     case Inst::kIdVpblendw:
     680             :     case Inst::kIdPblendw:
     681           0 :       return FormatterInternal_formatImmShuf(sb, u8, 1, 8);
     682             : 
     683           0 :     case Inst::kIdVpblendd:
     684           0 :       return FormatterInternal_formatImmShuf(sb, u8, 1, Support::min<uint32_t>(vecSize / 4, 8));
     685             : 
     686           0 :     case Inst::kIdVpclmulqdq:
     687             :     case Inst::kIdPclmulqdq:
     688           0 :       return FormatterInternal_formatImmBits(sb, u8, vpclmulqdq, ASMJIT_ARRAY_SIZE(vpclmulqdq));
     689             : 
     690           0 :     case Inst::kIdVroundpd:
     691             :     case Inst::kIdVroundps:
     692             :     case Inst::kIdVroundsd:
     693             :     case Inst::kIdVroundss:
     694             :     case Inst::kIdRoundpd:
     695             :     case Inst::kIdRoundps:
     696             :     case Inst::kIdRoundsd:
     697             :     case Inst::kIdRoundss:
     698           0 :       return FormatterInternal_formatImmBits(sb, u8, vroundxx, ASMJIT_ARRAY_SIZE(vroundxx));
     699             : 
     700           0 :     case Inst::kIdVshufpd:
     701             :     case Inst::kIdShufpd:
     702           0 :       return FormatterInternal_formatImmText(sb, u8, 1, 2, vshufpd, Support::min<uint32_t>(vecSize / 8, 8));
     703             : 
     704           0 :     case Inst::kIdVshufps:
     705             :     case Inst::kIdShufps:
     706           0 :       return FormatterInternal_formatImmText(sb, u8, 2, 4, vshufps, 4);
     707             : 
     708           0 :     case Inst::kIdVcvtps2ph:
     709           0 :       return FormatterInternal_formatImmBits(sb, u8, vroundxx, 1);
     710             : 
     711           0 :     case Inst::kIdVperm2f128:
     712             :     case Inst::kIdVperm2i128:
     713           0 :       return FormatterInternal_formatImmBits(sb, u8, vperm2x128, ASMJIT_ARRAY_SIZE(vperm2x128));
     714             : 
     715           0 :     case Inst::kIdVpermilpd:
     716           0 :       return FormatterInternal_formatImmShuf(sb, u8, 1, vecSize / 8);
     717             : 
     718           0 :     case Inst::kIdVpermilps:
     719           0 :       return FormatterInternal_formatImmShuf(sb, u8, 2, 4);
     720             : 
     721           0 :     case Inst::kIdVpshufd:
     722             :     case Inst::kIdPshufd:
     723           0 :       return FormatterInternal_formatImmShuf(sb, u8, 2, 4);
     724             : 
     725           0 :     case Inst::kIdVpshufhw:
     726             :     case Inst::kIdVpshuflw:
     727             :     case Inst::kIdPshufhw:
     728             :     case Inst::kIdPshuflw:
     729             :     case Inst::kIdPshufw:
     730           0 :       return FormatterInternal_formatImmShuf(sb, u8, 2, 4);
     731             : 
     732           0 :     case Inst::kIdVfixupimmpd:
     733             :     case Inst::kIdVfixupimmps:
     734             :     case Inst::kIdVfixupimmsd:
     735             :     case Inst::kIdVfixupimmss:
     736           0 :       return FormatterInternal_formatImmBits(sb, u8, vfixupimmxx, ASMJIT_ARRAY_SIZE(vfixupimmxx));
     737             : 
     738           0 :     case Inst::kIdVfpclasspd:
     739             :     case Inst::kIdVfpclassps:
     740             :     case Inst::kIdVfpclasssd:
     741             :     case Inst::kIdVfpclassss:
     742           0 :       return FormatterInternal_formatImmBits(sb, u8, vfpclassxx, ASMJIT_ARRAY_SIZE(vfpclassxx));
     743             : 
     744           0 :     case Inst::kIdVgetmantpd:
     745             :     case Inst::kIdVgetmantps:
     746             :     case Inst::kIdVgetmantsd:
     747             :     case Inst::kIdVgetmantss:
     748           0 :       return FormatterInternal_formatImmBits(sb, u8, vgetmantxx, ASMJIT_ARRAY_SIZE(vgetmantxx));
     749             : 
     750           0 :     case Inst::kIdVpcmpb:
     751             :     case Inst::kIdVpcmpd:
     752             :     case Inst::kIdVpcmpq:
     753             :     case Inst::kIdVpcmpw:
     754             :     case Inst::kIdVpcmpub:
     755             :     case Inst::kIdVpcmpud:
     756             :     case Inst::kIdVpcmpuq:
     757             :     case Inst::kIdVpcmpuw:
     758           0 :       return FormatterInternal_formatImmText(sb, u8, 3, 0, vpcmpx);
     759             : 
     760           0 :     case Inst::kIdVpcomb:
     761             :     case Inst::kIdVpcomd:
     762             :     case Inst::kIdVpcomq:
     763             :     case Inst::kIdVpcomw:
     764             :     case Inst::kIdVpcomub:
     765             :     case Inst::kIdVpcomud:
     766             :     case Inst::kIdVpcomuq:
     767             :     case Inst::kIdVpcomuw:
     768           0 :       return FormatterInternal_formatImmText(sb, u8, 3, 0, vpcomx);
     769             : 
     770           0 :     case Inst::kIdVpermq:
     771             :     case Inst::kIdVpermpd:
     772           0 :       return FormatterInternal_formatImmShuf(sb, u8, 2, 4);
     773             : 
     774           0 :     case Inst::kIdVpternlogd:
     775             :     case Inst::kIdVpternlogq:
     776           0 :       return FormatterInternal_formatImmShuf(sb, u8, 1, 8);
     777             : 
     778           0 :     case Inst::kIdVrangepd:
     779             :     case Inst::kIdVrangeps:
     780             :     case Inst::kIdVrangesd:
     781             :     case Inst::kIdVrangess:
     782           0 :       return FormatterInternal_formatImmBits(sb, u8, vrangexx, ASMJIT_ARRAY_SIZE(vrangexx));
     783             : 
     784           0 :     case Inst::kIdVreducepd:
     785             :     case Inst::kIdVreduceps:
     786             :     case Inst::kIdVreducesd:
     787             :     case Inst::kIdVreducess:
     788             :     case Inst::kIdVrndscalepd:
     789             :     case Inst::kIdVrndscaleps:
     790             :     case Inst::kIdVrndscalesd:
     791             :     case Inst::kIdVrndscaless:
     792           0 :       return FormatterInternal_formatImmBits(sb, u8, vreducexx_vrndscalexx, ASMJIT_ARRAY_SIZE(vreducexx_vrndscalexx));
     793             : 
     794           0 :     case Inst::kIdVshuff32x4:
     795             :     case Inst::kIdVshuff64x2:
     796             :     case Inst::kIdVshufi32x4:
     797             :     case Inst::kIdVshufi64x2: {
     798           0 :       uint32_t count = Support::max<uint32_t>(vecSize / 16, 2u);
     799           0 :       uint32_t bits = count <= 2 ? 1u : 2u;
     800           0 :       return FormatterInternal_formatImmShuf(sb, u8, bits, count);
     801             :     }
     802             : 
     803             :     default:
     804             :       return kErrorOk;
     805             :   }
     806             : }
     807             : 
     808             : // x86::FormatterInternal - Format Instruction
     809             : // ===========================================
     810             : 
     811           0 : ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction(
     812             :   String& sb,
     813             :   FormatFlags formatFlags,
     814             :   const BaseEmitter* emitter,
     815             :   Arch arch,
     816             :   const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept {
     817             : 
     818             :   InstId instId = inst.id();
     819             :   InstOptions options = inst.options();
     820             : 
     821             :   // Format instruction options and instruction mnemonic.
     822           0 :   if (instId < Inst::_kIdCount) {
     823             :     // VEX|EVEX options.
     824           0 :     if (Support::test(options, InstOptions::kX86_Vex))
     825           0 :       ASMJIT_PROPAGATE(sb.append("{vex} "));
     826             : 
     827           0 :     if (Support::test(options, InstOptions::kX86_Vex3))
     828           0 :       ASMJIT_PROPAGATE(sb.append("{vex3} "));
     829             : 
     830           0 :     if (Support::test(options, InstOptions::kX86_Evex))
     831           0 :       ASMJIT_PROPAGATE(sb.append("{evex} "));
     832             : 
     833             :     // MOD/RM and MOD/MR options
     834           0 :     if (Support::test(options, InstOptions::kX86_ModRM))
     835           0 :       ASMJIT_PROPAGATE(sb.append("{modrm} "));
     836           0 :     else if (Support::test(options, InstOptions::kX86_ModMR))
     837           0 :       ASMJIT_PROPAGATE(sb.append("{modmr} "));
     838             : 
     839             :     // SHORT|LONG options.
     840           0 :     if (Support::test(options, InstOptions::kShortForm))
     841           0 :       ASMJIT_PROPAGATE(sb.append("short "));
     842             : 
     843           0 :     if (Support::test(options, InstOptions::kLongForm))
     844           0 :       ASMJIT_PROPAGATE(sb.append("long "));
     845             : 
     846             :     // LOCK|XACQUIRE|XRELEASE options.
     847           0 :     if (Support::test(options, InstOptions::kX86_XAcquire))
     848           0 :       ASMJIT_PROPAGATE(sb.append("xacquire "));
     849             : 
     850           0 :     if (Support::test(options, InstOptions::kX86_XRelease))
     851           0 :       ASMJIT_PROPAGATE(sb.append("xrelease "));
     852             : 
     853           0 :     if (Support::test(options, InstOptions::kX86_Lock))
     854           0 :       ASMJIT_PROPAGATE(sb.append("lock "));
     855             : 
     856             :     // REP|REPNE options.
     857           0 :     if (Support::test(options, InstOptions::kX86_Rep | InstOptions::kX86_Repne)) {
     858           0 :       sb.append(Support::test(options, InstOptions::kX86_Rep) ? "rep " : "repnz ");
     859           0 :       if (inst.hasExtraReg()) {
     860           0 :         ASMJIT_PROPAGATE(sb.append("{"));
     861           0 :         ASMJIT_PROPAGATE(formatOperand(sb, formatFlags, emitter, arch, inst.extraReg().toReg<BaseReg>()));
     862           0 :         ASMJIT_PROPAGATE(sb.append("} "));
     863             :       }
     864             :     }
     865             : 
     866             :     // REX options.
     867           0 :     if (Support::test(options, InstOptions::kX86_Rex)) {
     868             :       const InstOptions kRXBWMask = InstOptions::kX86_OpCodeR |
     869             :                                     InstOptions::kX86_OpCodeX |
     870             :                                     InstOptions::kX86_OpCodeB |
     871             :                                     InstOptions::kX86_OpCodeW ;
     872           0 :       if (Support::test(options, kRXBWMask)) {
     873           0 :         ASMJIT_PROPAGATE(sb.append("rex."));
     874           0 :         if (Support::test(options, InstOptions::kX86_OpCodeR)) sb.append('r');
     875           0 :         if (Support::test(options, InstOptions::kX86_OpCodeX)) sb.append('x');
     876           0 :         if (Support::test(options, InstOptions::kX86_OpCodeB)) sb.append('b');
     877           0 :         if (Support::test(options, InstOptions::kX86_OpCodeW)) sb.append('w');
     878           0 :         sb.append(' ');
     879             :       }
     880             :       else {
     881           0 :         ASMJIT_PROPAGATE(sb.append("rex "));
     882             :       }
     883             :     }
     884             : 
     885           0 :     ASMJIT_PROPAGATE(InstInternal::instIdToString(arch, instId, sb));
     886             :   }
     887             :   else {
     888           0 :     ASMJIT_PROPAGATE(sb.appendFormat("[InstId=#%u]", unsigned(instId)));
     889             :   }
     890             : 
     891           0 :   for (uint32_t i = 0; i < opCount; i++) {
     892           0 :     const Operand_& op = operands[i];
     893           0 :     if (op.isNone()) break;
     894             : 
     895           0 :     ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", "));
     896           0 :     ASMJIT_PROPAGATE(formatOperand(sb, formatFlags, emitter, arch, op));
     897             : 
     898           0 :     if (op.isImm() && uint32_t(formatFlags & FormatFlags::kExplainImms)) {
     899             :       uint32_t vecSize = 16;
     900           0 :       for (uint32_t j = 0; j < opCount; j++)
     901           0 :         if (operands[j].isReg())
     902             :           vecSize = Support::max<uint32_t>(vecSize, operands[j].size());
     903           0 :       ASMJIT_PROPAGATE(FormatterInternal_explainConst(sb, formatFlags, instId, vecSize, op.as<Imm>()));
     904             :     }
     905             : 
     906             :     // Support AVX-512 masking - {k}{z}.
     907           0 :     if (i == 0) {
     908           0 :       if (inst.extraReg().group() == RegGroup::kX86_K) {
     909           0 :         ASMJIT_PROPAGATE(sb.append(" {"));
     910           0 :         ASMJIT_PROPAGATE(formatRegister(sb, formatFlags, emitter, arch, inst.extraReg().type(), inst.extraReg().id()));
     911           0 :         ASMJIT_PROPAGATE(sb.append('}'));
     912             : 
     913           0 :         if (Support::test(options, InstOptions::kX86_ZMask))
     914           0 :           ASMJIT_PROPAGATE(sb.append("{z}"));
     915             :       }
     916           0 :       else if (Support::test(options, InstOptions::kX86_ZMask)) {
     917           0 :         ASMJIT_PROPAGATE(sb.append(" {z}"));
     918             :       }
     919             :     }
     920             : 
     921             :     // Support AVX-512 broadcast - {1tox}.
     922           0 :     if (op.isMem() && op.as<Mem>().hasBroadcast()) {
     923           0 :       ASMJIT_PROPAGATE(sb.appendFormat(" {1to%u}", Support::bitMask(uint32_t(op.as<Mem>().getBroadcast()))));
     924             :     }
     925             :   }
     926             : 
     927             :   // Support AVX-512 embedded rounding and suppress-all-exceptions {sae}.
     928           0 :   if (inst.hasOption(InstOptions::kX86_ER | InstOptions::kX86_SAE)) {
     929           0 :     if (inst.hasOption(InstOptions::kX86_ER)) {
     930           0 :       uint32_t bits = uint32_t(inst.options() & InstOptions::kX86_ERMask) >> Support::ConstCTZ<uint32_t(InstOptions::kX86_ERMask)>::value;
     931             : 
     932           0 :       const char roundingModes[] = "rn\0rd\0ru\0rz";
     933           0 :       ASMJIT_PROPAGATE(sb.appendFormat(", {%s-sae}", roundingModes + bits * 3));
     934             :     }
     935             :     else {
     936           0 :       ASMJIT_PROPAGATE(sb.append(", {sae}"));
     937             :     }
     938             :   }
     939             : 
     940             :   return kErrorOk;
     941             : }
     942             : 
     943             : ASMJIT_END_SUB_NAMESPACE
     944             : 
     945             : #endif // !ASMJIT_NO_LOGGING
     946             : 
     947             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.16