LCOV - code coverage report
Current view: top level - asmjit - inst.h (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 28 46 60.9 %
Date: 2026-11-05 10:19:06 Functions: 1 1 100.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             : #ifndef ASMJIT_CORE_INST_H_INCLUDED
       8             : #define ASMJIT_CORE_INST_H_INCLUDED
       9             : 
      10             : #include "cpuinfo.h"
      11             : #include "operand.h"
      12             : #include "moved_string.h"
      13             : #include "support.h"
      14             : 
      15             : ASMJIT_BEGIN_NAMESPACE
      16             : 
      17             : //! \addtogroup asmjit_instruction_db
      18             : //! \{
      19             : 
      20             : //! Describes an instruction id and modifiers used together with the id.
      21             : //!
      22             : //! Each architecture has a set of valid instructions indexed from 0. Instruction with 0 id is, however, a special
      23             : //! instruction that describes a "no instruction" or "invalid instruction". Different architectures can assign a.
      24             : //! different instruction to the same id, each architecture typicall has its own instructions indexed from 1.
      25             : //!
      26             : //! Instruction identifiers listed by architecture:
      27             : //!
      28             : //!   - \ref x86::Inst (X86 and X86_64)
      29             : //!   - \ref a64::Inst (AArch64)
      30             : typedef uint32_t InstId;
      31             : 
      32             : //! Instruction id parts.
      33             : //!
      34             : //! A mask that specifies a bit-layout of \ref InstId.
      35             : enum class InstIdParts : uint32_t {
      36             :   // Common Masks
      37             :   // ------------
      38             : 
      39             :   //! Real id without any modifiers (always 16 least significant bits).
      40             :   kRealId   = 0x0000FFFFu,
      41             :   //! Instruction is abstract (or virtual, IR, etc...).
      42             :   kAbstract = 0x80000000u,
      43             : 
      44             :   // ARM Specific
      45             :   // ------------
      46             : 
      47             :   //! AArch32 first data type, used by ASIMD instructions (`inst.dt.dt2`).
      48             :   kA32_DT   = 0x000F0000u,
      49             :   //! AArch32 second data type, used by ASIMD instructions (`inst.dt.dt2`).
      50             :   kA32_DT2  = 0x00F00000u,
      51             :   //! AArch32/AArch64 condition code.
      52             :   kARM_Cond = 0x78000000u
      53             : };
      54             : 
      55             : //! Instruction options.
      56             : //!
      57             : //! Instruction options complement instruction identifier and attributes.
      58             : enum class InstOptions : uint32_t {
      59             :   //! No options.
      60             :   kNone = 0,
      61             : 
      62             :   //! Used internally by emitters for handling errors and rare cases.
      63             :   kReserved = 0x00000001u,
      64             : 
      65             :   //! Prevents following a jump during compilation (Compiler).
      66             :   kUnfollow = 0x00000002u,
      67             : 
      68             :   //! Overwrite the destination operand(s) (Compiler).
      69             :   //!
      70             :   //! Hint that is important for register liveness analysis. It tells the compiler that the destination operand will
      71             :   //! be overwritten now or by adjacent instructions. Compiler knows when a register is completely overwritten by a
      72             :   //! single instruction, for example you don't have to mark "movaps" or "pxor x, x", however, if a pair of
      73             :   //! instructions is used and the first of them doesn't completely overwrite the content of the destination,
      74             :   //! Compiler fails to mark that register as dead.
      75             :   //!
      76             :   //! X86 Specific
      77             :   //! ------------
      78             :   //!
      79             :   //!   - All instructions that always overwrite at least the size of the register the virtual-register uses, for
      80             :   //!     example "mov", "movq", "movaps" don't need the overwrite option to be used - conversion, shuffle, and
      81             :   //!     other miscellaneous instructions included.
      82             :   //!
      83             :   //!   - All instructions that clear the destination register if all operands are the same, for example "xor x, x",
      84             :   //!     "pcmpeqb x x", etc...
      85             :   //!
      86             :   //!   - Consecutive instructions that partially overwrite the variable until there is no old content require
      87             :   //!     `BaseCompiler::overwrite()` to be used. Some examples (not always the best use cases thought):
      88             :   //!
      89             :   //!     - `movlps xmm0, ?` followed by `movhps xmm0, ?` and vice versa
      90             :   //!     - `movlpd xmm0, ?` followed by `movhpd xmm0, ?` and vice versa
      91             :   //!     - `mov al, ?` followed by `and ax, 0xFF`
      92             :   //!     - `mov al, ?` followed by `mov ah, al`
      93             :   //!     - `pinsrq xmm0, ?, 0` followed by `pinsrq xmm0, ?, 1`
      94             :   //!
      95             :   //!   - If the allocated virtual register is used temporarily for scalar operations. For example if you allocate a
      96             :   //!     full vector like `x86::Compiler::newXmm()` and then use that vector for scalar operations you should use
      97             :   //!     `overwrite()` directive:
      98             :   //!
      99             :   //!     - `sqrtss x, y` - only LO element of `x` is changed, if you don't
     100             :   //!       use HI elements, use `compiler.overwrite().sqrtss(x, y)`.
     101             :   kOverwrite = 0x00000004u,
     102             : 
     103             :   //! Emit short-form of the instruction.
     104             :   kShortForm = 0x00000010u,
     105             :   //! Emit long-form of the instruction.
     106             :   kLongForm = 0x00000020u,
     107             : 
     108             :   //! Conditional jump is likely to be taken.
     109             :   kTaken = 0x00000040u,
     110             :   //! Conditional jump is unlikely to be taken.
     111             :   kNotTaken = 0x00000080u,
     112             : 
     113             :   // X86 & X64 Options
     114             :   // -----------------
     115             : 
     116             :   //! Use ModMR instead of ModRM if applicable.
     117             :   kX86_ModMR = 0x00000100u,
     118             :   //! Use ModRM instead of ModMR if applicable.
     119             :   kX86_ModRM = 0x00000200u,
     120             :   //! Use 3-byte VEX prefix if possible (AVX) (must be 0x00000400).
     121             :   kX86_Vex3 = 0x00000400u,
     122             :   //! Use VEX prefix when both VEX|EVEX prefixes are available (HINT: AVX_VNNI).
     123             :   kX86_Vex = 0x00000800u,
     124             :   //! Use 4-byte EVEX prefix if possible (AVX-512) (must be 0x00001000).
     125             :   kX86_Evex = 0x00001000u,
     126             : 
     127             :   //! LOCK prefix (lock-enabled instructions only).
     128             :   kX86_Lock = 0x00002000u,
     129             :   //! REP prefix (string instructions only).
     130             :   kX86_Rep = 0x00004000u,
     131             :   //! REPNE prefix (string instructions only).
     132             :   kX86_Repne = 0x00008000u,
     133             : 
     134             :   //! XACQUIRE prefix (only allowed instructions).
     135             :   kX86_XAcquire = 0x00010000u,
     136             :   //! XRELEASE prefix (only allowed instructions).
     137             :   kX86_XRelease = 0x00020000u,
     138             : 
     139             :   //! AVX-512: embedded-rounding {er} and implicit {sae}.
     140             :   kX86_ER = 0x00040000u,
     141             :   //! AVX-512: suppress-all-exceptions {sae}.
     142             :   kX86_SAE = 0x00080000u,
     143             :   //! AVX-512: round-to-nearest (even) {rn-sae} (bits 00).
     144             :   kX86_RN_SAE = 0x00000000u,
     145             :   //! AVX-512: round-down (toward -inf) {rd-sae} (bits 01).
     146             :   kX86_RD_SAE = 0x00200000u,
     147             :   //! AVX-512: round-up (toward +inf) {ru-sae} (bits 10).
     148             :   kX86_RU_SAE = 0x00400000u,
     149             :   //! AVX-512: round-toward-zero (truncate) {rz-sae} (bits 11).
     150             :   kX86_RZ_SAE = 0x00600000u,
     151             :   //! AVX-512: Use zeroing {k}{z} instead of merging {k}.
     152             :   kX86_ZMask = 0x00800000u,
     153             : 
     154             :   //! AVX-512: Mask to get embedded rounding bits (2 bits).
     155             :   kX86_ERMask = kX86_RZ_SAE,
     156             :   //! AVX-512: Mask of all possible AVX-512 options except EVEX prefix flag.
     157             :   kX86_AVX512Mask = 0x00FC0000u,
     158             : 
     159             :   //! Force REX.B and/or VEX.B field (X64 only).
     160             :   kX86_OpCodeB = 0x01000000u,
     161             :   //! Force REX.X and/or VEX.X field (X64 only).
     162             :   kX86_OpCodeX = 0x02000000u,
     163             :   //! Force REX.R and/or VEX.R field (X64 only).
     164             :   kX86_OpCodeR = 0x04000000u,
     165             :   //! Force REX.W and/or VEX.W field (X64 only).
     166             :   kX86_OpCodeW = 0x08000000u,
     167             :   //! Force REX prefix (X64 only).
     168             :   kX86_Rex = 0x40000000u,
     169             :   //! Invalid REX prefix (set by X86 or when AH|BH|CH|DH regs are used on X64).
     170             :   kX86_InvalidRex = 0x80000000u
     171             : };
     172     1140989 : ASMJIT_DEFINE_ENUM_FLAGS(InstOptions)
     173             : 
     174             : //! Instruction control flow.
     175             : enum class InstControlFlow : uint32_t {
     176             :   //! Regular instruction.
     177             :   kRegular = 0u,
     178             :   //! Unconditional jump.
     179             :   kJump = 1u,
     180             :   //! Conditional jump (branch).
     181             :   kBranch = 2u,
     182             :   //! Function call.
     183             :   kCall = 3u,
     184             :   //! Function return.
     185             :   kReturn = 4u,
     186             : 
     187             :   //! Maximum value of `InstType`.
     188             :   kMaxValue = kReturn
     189             : };
     190             : 
     191             : //! Hint that is used when both input operands to the instruction are the same.
     192             : //!
     193             : //! Provides hints to the instrution RW query regarding special cases in which two or more operands are the same
     194             : //! registers. This is required by instructions such as XOR, AND, OR, SUB, etc... These hints will influence the
     195             : //! RW operations query.
     196             : enum class InstSameRegHint : uint8_t {
     197             :   //! No special handling.
     198             :   kNone = 0,
     199             :   //! Operands become read-only, the operation doesn't change the content - `X & X` and similar.
     200             :   kRO = 1,
     201             :   //! Operands become write-only, the content of the input(s) don't matter - `X ^ X`, `X - X`, and similar.
     202             :   kWO = 2
     203             : };
     204             : 
     205             : //! Instruction id, options, and extraReg in a single structure. This structure exists mainly to simplify analysis
     206             : //! and validation API that requires `BaseInst` and `Operand[]` array.
     207             : class BaseInst {
     208             : public:
     209             :   //! \name Members
     210             :   //! \{
     211             : 
     212             :   //! Instruction id with modifiers.
     213             :   InstId _id;
     214             :   //! Instruction options.
     215             :   InstOptions _options;
     216             :   //! Extra register used by the instruction (either REP register or AVX-512 selector).
     217             :   RegOnly _extraReg;
     218             : 
     219             :   enum Id : uint32_t {
     220             :     //! Invalid or uninitialized instruction id.
     221             :     kIdNone = 0x00000000u,
     222             :     //! Abstract instruction (BaseBuilder and BaseCompiler).
     223             :     kIdAbstract = 0x80000000u
     224             :   };
     225             : 
     226             :   //! \}
     227             : 
     228             :   //! \name Construction & Destruction
     229             :   //! \{
     230             : 
     231             :   //! Creates a new BaseInst instance with `id` and `options` set.
     232             :   //!
     233             :   //! Default values of `id` and `options` are zero, which means 'none' instruction. Such instruction is guaranteed
     234             :   //! to never exist for any architecture supported by AsmJit.
     235             :   inline explicit BaseInst(InstId instId = 0, InstOptions options = InstOptions::kNone) noexcept
     236      419501 :     : _id(instId),
     237      419501 :       _options(options),
     238      419501 :       _extraReg() {}
     239             : 
     240             :   inline BaseInst(InstId instId, InstOptions options, const RegOnly& extraReg) noexcept
     241           0 :     : _id(instId),
     242           0 :       _options(options),
     243           0 :       _extraReg(extraReg) {}
     244             : 
     245             :   inline BaseInst(InstId instId, InstOptions options, const BaseReg& extraReg) noexcept
     246             :     : _id(instId),
     247             :       _options(options),
     248             :       _extraReg { extraReg.signature(), extraReg.id() } {}
     249             : 
     250             :   //! \}
     251             : 
     252             :   //! \name Instruction id and modifiers
     253             :   //! \{
     254             : 
     255             :   //! Returns the instruction id with modifiers.
     256     1116369 :   inline InstId id() const noexcept { return _id; }
     257             :   //! Sets the instruction id and modiiers from `id`.
     258           0 :   inline void setId(InstId id) noexcept { _id = id; }
     259             :   //! Resets the instruction id and modifiers to zero, see \ref kIdNone.
     260             :   inline void resetId() noexcept { _id = 0; }
     261             : 
     262             :   //! Returns a real instruction id that doesn't contain any modifiers.
     263           0 :   inline InstId realId() const noexcept { return _id & uint32_t(InstIdParts::kRealId); }
     264             : 
     265             :   template<InstIdParts kPart>
     266             :   inline uint32_t getInstIdPart() const noexcept {
     267           0 :     return (uint32_t(_id) & uint32_t(kPart)) >> Support::ConstCTZ<uint32_t(kPart)>::value;
     268             :   }
     269             : 
     270             :   template<InstIdParts kPart>
     271             :   inline void setInstIdPart(uint32_t value) noexcept {
     272             :     _id = (_id & ~uint32_t(kPart)) | (value << Support::ConstCTZ<uint32_t(kPart)>::value);
     273             :   }
     274             : 
     275             :   //! \}
     276             : 
     277             :   //! \name Instruction Options
     278             :   //! \{
     279             : 
     280      392009 :   inline InstOptions options() const noexcept { return _options; }
     281           0 :   inline bool hasOption(InstOptions option) const noexcept { return Support::test(_options, option); }
     282             :   inline void setOptions(InstOptions options) noexcept { _options = options; }
     283             :   inline void addOptions(InstOptions options) noexcept { _options |= options; }
     284             :   inline void clearOptions(InstOptions options) noexcept { _options &= ~options; }
     285             :   inline void resetOptions() noexcept { _options = InstOptions::kNone; }
     286             : 
     287             :   //! \}
     288             : 
     289             :   //! \name Extra Register
     290             :   //! \{
     291             : 
     292             :   inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); }
     293             :   inline RegOnly& extraReg() noexcept { return _extraReg; }
     294             :   inline const RegOnly& extraReg() const noexcept { return _extraReg; }
     295             :   inline void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); }
     296             :   inline void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); }
     297             :   inline void resetExtraReg() noexcept { _extraReg.reset(); }
     298             : 
     299             :   //! \}
     300             : 
     301             :   //! \name ARM Specific
     302             :   //! \{
     303             : 
     304           0 :   inline arm::CondCode armCondCode() const noexcept { return (arm::CondCode)getInstIdPart<InstIdParts::kARM_Cond>(); }
     305             :   inline void setArmCondCode(arm::CondCode cc) noexcept { setInstIdPart<InstIdParts::kARM_Cond>(uint32_t(cc)); }
     306             : 
     307             :   //! \}
     308             : 
     309             :   //! \name Statics
     310             :   //! \{
     311             : 
     312             :   static inline constexpr InstId composeARMInstId(uint32_t id, arm::CondCode cc) noexcept {
     313           0 :     return id | (uint32_t(cc) << Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value);
     314             :   }
     315             : 
     316             :   static inline constexpr InstId extractRealId(uint32_t id) noexcept {
     317           0 :     return id & uint32_t(InstIdParts::kRealId);
     318             :   }
     319             : 
     320             :   static inline constexpr arm::CondCode extractARMCondCode(uint32_t id) noexcept {
     321           0 :     return (arm::CondCode)((uint32_t(id) & uint32_t(InstIdParts::kARM_Cond)) >> Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value);
     322             :   }
     323             : 
     324             :   //! \}
     325             : };
     326             : 
     327             : //! CPU read/write flags used by \ref InstRWInfo.
     328             : //!
     329             : //! These flags can be used to get a basic overview about CPU specifics flags used by instructions.
     330             : enum class CpuRWFlags : uint32_t {
     331             :   //! No flags.
     332             :   kNone = 0x00000000u,
     333             : 
     334             :   // Common RW Flags (0x000000FF)
     335             :   // ----------------------------
     336             : 
     337             :   //! Carry flag.
     338             :   kCF = 0x00000001u,
     339             :   //! Signed overflow flag.
     340             :   kOF = 0x00000002u,
     341             :   //! Sign flag (negative/sign, if set).
     342             :   kSF = 0x00000004u,
     343             :   //! Zero and/or equality flag (1 if zero/equal).
     344             :   kZF = 0x00000008u,
     345             : 
     346             :   // X86 Specific RW Flags (0xFFFFFF00)
     347             :   // ----------------------------------
     348             : 
     349             :   //! Carry flag (X86, X86_64).
     350             :   kX86_CF = kCF,
     351             :   //! Overflow flag (X86, X86_64).
     352             :   kX86_OF = kOF,
     353             :   //! Sign flag (X86, X86_64).
     354             :   kX86_SF = kSF,
     355             :   //! Zero flag (X86, X86_64).
     356             :   kX86_ZF = kZF,
     357             : 
     358             :   //! Adjust flag (X86, X86_64).
     359             :   kX86_AF = 0x00000100u,
     360             :   //! Parity flag (X86, X86_64).
     361             :   kX86_PF = 0x00000200u,
     362             :   //! Direction flag (X86, X86_64).
     363             :   kX86_DF = 0x00000400u,
     364             :   //! Interrupt enable flag (X86, X86_64).
     365             :   kX86_IF = 0x00000800u,
     366             : 
     367             :   //! Alignment check flag (X86, X86_64).
     368             :   kX86_AC = 0x00001000u,
     369             : 
     370             :   //! FPU C0 status flag (X86, X86_64).
     371             :   kX86_C0 = 0x00010000u,
     372             :   //! FPU C1 status flag (X86, X86_64).
     373             :   kX86_C1 = 0x00020000u,
     374             :   //! FPU C2 status flag (X86, X86_64).
     375             :   kX86_C2 = 0x00040000u,
     376             :   //! FPU C3 status flag (X86, X86_64).
     377             :   kX86_C3 = 0x00080000u
     378             : };
     379             : ASMJIT_DEFINE_ENUM_FLAGS(CpuRWFlags)
     380             : 
     381             : //! Operand read/write flags describe how the operand is accessed and some additional features.
     382             : enum class OpRWFlags {
     383             :   //! No flags.
     384             :   kNone = 0,
     385             : 
     386             :   //! Operand is read.
     387             :   kRead = 0x00000001u,
     388             : 
     389             :   //! Operand is written.
     390             :   kWrite = 0x00000002u,
     391             : 
     392             :   //! Operand is both read and written.
     393             :   kRW = 0x00000003u,
     394             : 
     395             :   //! Register operand can be replaced by a memory operand.
     396             :   kRegMem = 0x00000004u,
     397             : 
     398             :   //! The register must be allocated to the index of the previous register + 1.
     399             :   //!
     400             :   //! This flag is used by all architectures to describe instructions that use consecutive registers, where only the
     401             :   //! first one is encoded in the instruction, and the others are just a sequence that starts with the first one. On
     402             :   //! X86/X86_64 architecture this is used by instructions such as V4FMADDPS, V4FMADDSS, V4FNMADDPS, V4FNMADDSS,
     403             :   //! VP4DPWSSD, VP4DPWSSDS, VP2INTERSECTD, and VP2INTERSECTQ. On ARM/AArch64 this is used by vector load and store
     404             :   //! instructions that can load or store multiple registers at once.
     405             :   kConsecutive = 0x00000008u,
     406             : 
     407             :   //! The `extendByteMask()` represents a zero extension.
     408             :   kZExt = 0x00000010u,
     409             : 
     410             :   //! Register operand must use \ref OpRWInfo::physId().
     411             :   kRegPhysId = 0x00000100u,
     412             :   //! Base register of a memory operand must use \ref OpRWInfo::physId().
     413             :   kMemPhysId = 0x00000200u,
     414             : 
     415             :   //! This memory operand is only used to encode registers and doesn't access memory.
     416             :   //!
     417             :   //! X86 Specific
     418             :   //! ------------
     419             :   //!
     420             :   //! Instructions that use such feature include BNDLDX, BNDSTX, and LEA.
     421             :   kMemFake = 0x000000400u,
     422             : 
     423             :   //! Base register of the memory operand will be read.
     424             :   kMemBaseRead = 0x00001000u,
     425             :   //! Base register of the memory operand will be written.
     426             :   kMemBaseWrite = 0x00002000u,
     427             :   //! Base register of the memory operand will be read & written.
     428             :   kMemBaseRW = 0x00003000u,
     429             : 
     430             :   //! Index register of the memory operand will be read.
     431             :   kMemIndexRead = 0x00004000u,
     432             :   //! Index register of the memory operand will be written.
     433             :   kMemIndexWrite = 0x00008000u,
     434             :   //! Index register of the memory operand will be read & written.
     435             :   kMemIndexRW = 0x0000C000u,
     436             : 
     437             :   //! Base register of the memory operand will be modified before the operation.
     438             :   kMemBasePreModify = 0x00010000u,
     439             :   //! Base register of the memory operand will be modified after the operation.
     440             :   kMemBasePostModify = 0x00020000u
     441             : };
     442     1247851 : ASMJIT_DEFINE_ENUM_FLAGS(OpRWFlags)
     443             : 
     444             : // Don't remove these asserts. Read/Write flags are used extensively
     445             : // by Compiler and they must always be compatible with constants below.
     446             : static_assert(uint32_t(OpRWFlags::kRead) == 0x1, "OpRWFlags::kRead flag must be 0x1");
     447             : static_assert(uint32_t(OpRWFlags::kWrite) == 0x2, "OpRWFlags::kWrite flag must be 0x2");
     448             : static_assert(uint32_t(OpRWFlags::kRegMem) == 0x4, "OpRWFlags::kRegMem flag must be 0x4");
     449             : 
     450             : //! Read/Write information related to a single operand, used by \ref InstRWInfo.
     451             : struct OpRWInfo {
     452             :   //! \name Members
     453             :   //! \{
     454             : 
     455             :   //! Read/Write flags.
     456             :   OpRWFlags _opFlags;
     457             :   //! Physical register index, if required.
     458             :   uint8_t _physId;
     459             :   //! Size of a possible memory operand that can replace a register operand.
     460             :   uint8_t _rmSize;
     461             :   //! If non-zero, then this is a consecutive lead register, and the value describes how many registers follow.
     462             :   uint8_t _consecutiveLeadCount;
     463             :   //! Reserved for future use.
     464             :   uint8_t _reserved[1];
     465             :   //! Read bit-mask where each bit represents one byte read from Reg/Mem.
     466             :   uint64_t _readByteMask;
     467             :   //! Write bit-mask where each bit represents one byte written to Reg/Mem.
     468             :   uint64_t _writeByteMask;
     469             :   //! Zero/Sign extend bit-mask where each bit represents one byte written to Reg/Mem.
     470             :   uint64_t _extendByteMask;
     471             : 
     472             :   //! \}
     473             : 
     474             :   //! \name Reset
     475             :   //! \{
     476             : 
     477             :   //! Resets this operand information to all zeros.
     478      394528 :   inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
     479             : 
     480             :   //! Resets this operand info (resets all members) and set common information
     481             :   //! to the given `opFlags`, `regSize`, and possibly `physId`.
     482             :   inline void reset(OpRWFlags opFlags, uint32_t regSize, uint32_t physId = BaseReg::kIdBad) noexcept {
     483       88236 :     _opFlags = opFlags;
     484       88236 :     _physId = uint8_t(physId);
     485       88236 :     _rmSize = Support::test(opFlags, OpRWFlags::kRegMem) ? uint8_t(regSize) : uint8_t(0);
     486       88236 :     _consecutiveLeadCount = 0;
     487             :     _resetReserved();
     488             : 
     489             :     uint64_t mask = Support::lsbMask<uint64_t>(regSize);
     490       88236 :     _readByteMask = Support::test(opFlags, OpRWFlags::kRead) ? mask : uint64_t(0);
     491       88236 :     _writeByteMask = Support::test(opFlags, OpRWFlags::kWrite) ? mask : uint64_t(0);
     492       88236 :     _extendByteMask = 0;
     493           0 :   }
     494             : 
     495             :   inline void _resetReserved() noexcept {
     496      646381 :     _reserved[0] = 0;
     497             :   }
     498             : 
     499             :   //! \}
     500             : 
     501             :   //! \name Operand Flags
     502             :   //! \{
     503             : 
     504             :   //! Returns operand flags.
     505      646381 :   inline OpRWFlags opFlags() const noexcept { return _opFlags; }
     506             :   //! Tests whether operand flags contain the given `flag`.
     507     1062578 :   inline bool hasOpFlag(OpRWFlags flag) const noexcept { return Support::test(_opFlags, flag); }
     508             : 
     509             :   //! Adds the given `flags` to operand flags.
     510       70974 :   inline void addOpFlags(OpRWFlags flags) noexcept { _opFlags |= flags; }
     511             :   //! Removes the given `flags` from operand flags.
     512             :   inline void clearOpFlags(OpRWFlags flags) noexcept { _opFlags &= ~flags; }
     513             : 
     514             :   //! Tests whether this operand is read from.
     515             :   inline bool isRead() const noexcept { return hasOpFlag(OpRWFlags::kRead); }
     516             :   //! Tests whether this operand is written to.
     517             :   inline bool isWrite() const noexcept { return hasOpFlag(OpRWFlags::kWrite); }
     518             :   //! Tests whether this operand is both read and write.
     519             :   inline bool isReadWrite() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRW; }
     520             :   //! Tests whether this operand is read only.
     521             :   inline bool isReadOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRead; }
     522             :   //! Tests whether this operand is write only.
     523             :   inline bool isWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kWrite; }
     524             : 
     525             :   //! Returns the type of a lead register, which is followed by consecutive registers.
     526      575407 :   inline uint32_t consecutiveLeadCount() const noexcept { return _consecutiveLeadCount; }
     527             : 
     528             :   //! Tests whether this operand is Reg/Mem
     529             :   //!
     530             :   //! Reg/Mem operands can use either register or memory.
     531             :   inline bool isRm() const noexcept { return hasOpFlag(OpRWFlags::kRegMem); }
     532             : 
     533             :   //! Tests whether the operand will be zero extended.
     534             :   inline bool isZExt() const noexcept { return hasOpFlag(OpRWFlags::kZExt); }
     535             : 
     536             :   //! \}
     537             : 
     538             :   //! \name Memory Flags
     539             :   //! \{
     540             : 
     541             :   //! Tests whether this is a fake memory operand, which is only used, because of encoding. Fake memory operands do
     542             :   //! not access any memory, they are only used to encode registers.
     543             :   inline bool isMemFake() const noexcept { return hasOpFlag(OpRWFlags::kMemFake); }
     544             : 
     545             :   //! Tests whether the instruction's memory BASE register is used.
     546             :   inline bool isMemBaseUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRW); }
     547             :   //! Tests whether the instruction reads from its BASE registers.
     548             :   inline bool isMemBaseRead() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRead); }
     549             :   //! Tests whether the instruction writes to its BASE registers.
     550             :   inline bool isMemBaseWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseWrite); }
     551             :   //! Tests whether the instruction reads and writes from/to its BASE registers.
     552             :   inline bool isMemBaseReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRW; }
     553             :   //! Tests whether the instruction only reads from its BASE registers.
     554             :   inline bool isMemBaseReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRead; }
     555             :   //! Tests whether the instruction only writes to its BASE registers.
     556             :   inline bool isMemBaseWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseWrite; }
     557             : 
     558             :   //! Tests whether the instruction modifies the BASE register before it uses it to calculate the target address.
     559             :   inline bool isMemBasePreModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePreModify); }
     560             :   //! Tests whether the instruction modifies the BASE register after it uses it to calculate the target address.
     561             :   inline bool isMemBasePostModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePostModify); }
     562             : 
     563             :   //! Tests whether the instruction's memory INDEX register is used.
     564             :   inline bool isMemIndexUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRW); }
     565             :   //! Tests whether the instruction reads the INDEX registers.
     566             :   inline bool isMemIndexRead() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRead); }
     567             :   //! Tests whether the instruction writes to its INDEX registers.
     568             :   inline bool isMemIndexWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexWrite); }
     569             :   //! Tests whether the instruction reads and writes from/to its INDEX registers.
     570             :   inline bool isMemIndexReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRW; }
     571             :   //! Tests whether the instruction only reads from its INDEX registers.
     572             :   inline bool isMemIndexReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRead; }
     573             :   //! Tests whether the instruction only writes to its INDEX registers.
     574             :   inline bool isMemIndexWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexWrite; }
     575             : 
     576             :   //! \}
     577             : 
     578             :   //! \name Physical Register ID
     579             :   //! \{
     580             : 
     581             :   //! Returns a physical id of the register that is fixed for this operand.
     582             :   //!
     583             :   //! Returns \ref BaseReg::kIdBad if any register can be used.
     584           0 :   inline uint32_t physId() const noexcept { return _physId; }
     585             :   //! Tests whether \ref physId() would return a valid physical register id.
     586             :   inline bool hasPhysId() const noexcept { return _physId != BaseReg::kIdBad; }
     587             :   //! Sets physical register id, which would be fixed for this operand.
     588             :   inline void setPhysId(uint32_t physId) noexcept { _physId = uint8_t(physId); }
     589             : 
     590             :   //! \}
     591             : 
     592             :   //! \name Reg/Mem Information
     593             :   //! \{
     594             : 
     595             :   //! Returns Reg/Mem size of the operand.
     596      575407 :   inline uint32_t rmSize() const noexcept { return _rmSize; }
     597             :   //! Sets Reg/Mem size of the operand.
     598      114299 :   inline void setRmSize(uint32_t rmSize) noexcept { _rmSize = uint8_t(rmSize); }
     599             : 
     600             :   //! \}
     601             : 
     602             :   //! \name Read & Write Masks
     603             :   //! \{
     604             : 
     605             :   //! Returns read mask.
     606             :   inline uint64_t readByteMask() const noexcept { return _readByteMask; }
     607             :   //! Returns write mask.
     608           0 :   inline uint64_t writeByteMask() const noexcept { return _writeByteMask; }
     609             :   //! Returns extend mask.
     610      294583 :   inline uint64_t extendByteMask() const noexcept { return _extendByteMask; }
     611             : 
     612             :   //! Sets read mask.
     613           0 :   inline void setReadByteMask(uint64_t mask) noexcept { _readByteMask = mask; }
     614             :   //! Sets write mask.
     615           0 :   inline void setWriteByteMask(uint64_t mask) noexcept { _writeByteMask = mask; }
     616             :   //! Sets externd mask.
     617      206347 :   inline void setExtendByteMask(uint64_t mask) noexcept { _extendByteMask = mask; }
     618             : 
     619             :   //! \}
     620             : };
     621             : 
     622             : //! Flags used by \ref InstRWInfo.
     623             : enum class InstRWFlags : uint32_t {
     624             :   //! No flags.
     625             :   kNone = 0x00000000u,
     626             : 
     627             :   //! Describes a move operation.
     628             :   //!
     629             :   //! This flag is used by RA to eliminate moves that are guaranteed to be moves only.
     630             :   kMovOp = 0x00000001u
     631             : };
     632      159210 : ASMJIT_DEFINE_ENUM_FLAGS(InstRWFlags)
     633             : 
     634             : //! Read/Write information of an instruction.
     635             : struct InstRWInfo {
     636             :   //! \name Members
     637             :   //! \{
     638             : 
     639             :   //! Instruction flags (there are no flags at the moment, this field is reserved).
     640             :   InstRWFlags _instFlags;
     641             :   //! CPU flags read.
     642             :   CpuRWFlags _readFlags;
     643             :   //! CPU flags written.
     644             :   CpuRWFlags _writeFlags;
     645             :   //! Count of operands.
     646             :   uint8_t _opCount;
     647             :   //! CPU feature required for replacing register operand with memory operand.
     648             :   uint8_t _rmFeature;
     649             :   //! Reserved for future use.
     650             :   uint8_t _reserved[18];
     651             :   //! Read/Write onfo of extra register (rep{} or kz{}).
     652             :   OpRWInfo _extraReg;
     653             :   //! Read/Write info of instruction operands.
     654             :   OpRWInfo _operands[Globals::kMaxOpCount];
     655             : 
     656             :   //! \}
     657             : 
     658             :   //! \name Commons
     659             :   //! \{
     660             : 
     661             :   //! Resets this RW information to all zeros.
     662             :   inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
     663             : 
     664             :   //! \}
     665             : 
     666             :   //! \name Instruction Flags
     667             :   //! \{
     668             : 
     669             :   //! Returns flags associated with the instruction, see \ref InstRWFlags.
     670      304316 :   inline InstRWFlags instFlags() const noexcept { return _instFlags; }
     671             : 
     672             :   //! Tests whether the instruction flags contain `flag`.
     673      520396 :   inline bool hasInstFlag(InstRWFlags flag) const noexcept { return Support::test(_instFlags, flag); }
     674             : 
     675             :   //! Tests whether the instruction flags contain \ref InstRWFlags::kMovOp.
     676             :   inline bool isMovOp() const noexcept { return hasInstFlag(InstRWFlags::kMovOp); }
     677             : 
     678             :   //! \}
     679             : 
     680             :   //! \name CPU Flags Information
     681             :   //! \{
     682             : 
     683             :   //! Returns a mask of CPU flags read.
     684             :   inline CpuRWFlags readFlags() const noexcept { return _readFlags; }
     685             :   //! Returns a mask of CPU flags written.
     686             :   inline CpuRWFlags writeFlags() const noexcept { return _writeFlags; }
     687             : 
     688             :   //! \}
     689             : 
     690             :   //! \name Reg/Mem Information
     691             :   //! \{
     692             : 
     693             :   //! Returns the CPU feature required to replace a register operand with memory operand. If the returned feature is
     694             :   //! zero (none) then this instruction either doesn't provide memory operand combination or there is no extra CPU
     695             :   //! feature required.
     696             :   //!
     697             :   //! X86 Specific
     698             :   //! ------------
     699             :   //!
     700             :   //! Some AVX+ instructions may require extra features for replacing registers with memory operands, for example
     701             :   //! VPSLLDQ instruction only supports `vpslldq reg, reg, imm` combination on AVX/AVX2 capable CPUs and requires
     702             :   //! AVX-512 for `vpslldq reg, mem, imm` combination.
     703      575407 :   inline uint32_t rmFeature() const noexcept { return _rmFeature; }
     704             : 
     705             :   //! \}
     706             : 
     707             :   //! \name Operand Read/Write Information
     708             :   //! \{
     709             : 
     710             :   //! Returns RW information of extra register operand (extraReg).
     711             :   inline const OpRWInfo& extraReg() const noexcept { return _extraReg; }
     712             : 
     713             :   //! Returns RW information of all instruction's operands.
     714             :   inline const OpRWInfo* operands() const noexcept { return _operands; }
     715             : 
     716             :   //! Returns RW information of the operand at the given `index`.
     717             :   inline const OpRWInfo& operand(size_t index) const noexcept {
     718             :     ASMJIT_ASSERT(index < Globals::kMaxOpCount);
     719             :     return _operands[index];
     720             :   }
     721             : 
     722             :   //! Returns the number of operands this instruction has.
     723           0 :   inline uint32_t opCount() const noexcept { return _opCount; }
     724             : 
     725             :   //! \}
     726             : };
     727             : 
     728             : //! Validation flags that can be used with \ref InstAPI::validate().
     729             : enum class ValidationFlags : uint32_t {
     730             :   //! No flags.
     731             :   kNone = 0,
     732             :   //! Allow virtual registers in the instruction.
     733             :   kEnableVirtRegs = 0x01u
     734             : };
     735           0 : ASMJIT_DEFINE_ENUM_FLAGS(ValidationFlags)
     736             : 
     737             : //! Instruction API.
     738             : namespace InstAPI {
     739             : 
     740             : #ifndef ASMJIT_NO_TEXT
     741             : //! Appends the name of the instruction specified by `instId` and `instOptions` into the `output` string.
     742             : //!
     743             : //! \note Instruction options would only affect instruction prefix & suffix, other options would be ignored.
     744             : //! If `instOptions` is zero then only raw instruction name (without any additional text) will be appended.
     745             : ASMJIT_API Error instIdToString(Arch arch, InstId instId, String& output) noexcept;
     746             : 
     747             : //! Parses an instruction name in the given string `s`. Length is specified by `len` argument, which can be
     748             : //! `SIZE_MAX` if `s` is known to be null terminated.
     749             : //!
     750             : //! Returns the parsed instruction id or \ref BaseInst::kIdNone if no such instruction exists.
     751             : ASMJIT_API InstId stringToInstId(Arch arch, const char* s, size_t len) noexcept;
     752             : #endif // !ASMJIT_NO_TEXT
     753             : 
     754             : #ifndef ASMJIT_NO_VALIDATION
     755             : //! Validates the given instruction considering the given `validationFlags`.
     756             : ASMJIT_API Error validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags = ValidationFlags::kNone) noexcept;
     757             : #endif // !ASMJIT_NO_VALIDATION
     758             : 
     759             : #ifndef ASMJIT_NO_INTROSPECTION
     760             : //! Gets Read/Write information of the given instruction.
     761             : ASMJIT_API Error queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept;
     762             : 
     763             : //! Gets CPU features required by the given instruction.
     764             : ASMJIT_API Error queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept;
     765             : #endif // !ASMJIT_NO_INTROSPECTION
     766             : 
     767             : } // {InstAPI}
     768             : 
     769             : //! \}
     770             : 
     771             : ASMJIT_END_NAMESPACE
     772             : 
     773             : #endif // ASMJIT_CORE_INST_H_INCLUDED
     774             : 
     775             : #endif // __PLUMED_HAS_ASMJIT

Generated by: LCOV version 1.16