LCOV - code coverage report
Current view: top level - asmjit - x86misc.h (source / functions) Hit Total Coverage
Test: plumed test coverage (other modules) Lines: 22 37 59.5 %
Date: 2024-10-18 14:00:27 Functions: 0 0 -

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             : Copyright (c) 2008-2017, Petr Kobalicek
       3             : 
       4             : This software is provided 'as-is', without any express or implied
       5             : warranty. In no event will the authors be held liable for any damages
       6             : arising from the use of this software.
       7             : 
       8             : Permission is granted to anyone to use this software for any purpose,
       9             : including commercial applications, and to alter it and redistribute it
      10             : freely, subject to the following restrictions:
      11             : 
      12             : 1. The origin of this software must not be misrepresented; you must not
      13             :    claim that you wrote the original software. If you use this software
      14             :    in a product, an acknowledgment in the product documentation would be
      15             :    appreciated but is not required.
      16             : 2. Altered source versions must be plainly marked as such, and must not be
      17             :    misrepresented as being the original software.
      18             : 3. This notice may not be removed or altered from any source distribution.
      19             : +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
      20             : #ifndef __PLUMED_asmjit_x86misc_h
      21             : #define __PLUMED_asmjit_x86misc_h
      22             : #ifdef __PLUMED_HAS_ASMJIT
      23             : #pragma GCC diagnostic push
      24             : #pragma GCC diagnostic ignored "-Wpedantic"
      25             : // [AsmJit]
      26             : // Complete x86/x64 JIT and Remote Assembler for C++.
      27             : //
      28             : // [License]
      29             : // Zlib - See LICENSE.md file in the package.
      30             : 
      31             : // [Guard]
      32             : #ifndef _ASMJIT_X86_X86MISC_H
      33             : #define _ASMJIT_X86_X86MISC_H
      34             : 
      35             : // [Dependencies]
      36             : #include "./x86operand.h"
      37             : 
      38             : // [Api-Begin]
      39             : #include "./asmjit_apibegin.h"
      40             : 
      41             : namespace PLMD {
      42             : namespace asmjit {
      43             : 
      44             : //! \addtogroup asmjit_x86
      45             : //! \{
      46             : 
      47             : // ============================================================================
      48             : // [asmjit::X86RegCount]
      49             : // ============================================================================
      50             : 
      51             : //! \internal
      52             : //!
      53             : //! X86/X64 registers count.
      54             : //!
      55             : //! Since the number of registers changed across CPU generations `X86RegCount`
      56             : //! class is used by `X86Assembler` and `X86Compiler` to provide a way to get
      57             : //! number of available registers dynamically. 32-bit mode offers always only
      58             : //! 8 registers of all classes, however, 64-bit mode offers 16 GP registers and
      59             : //! 16 XMM/YMM/ZMM registers. AVX512 instruction set doubles the number of SIMD
      60             : //! registers (XMM/YMM/ZMM) to 32, this mode has to be explicitly enabled to
      61             : //! take effect as it changes some assumptions.
      62             : //!
      63             : //! `X86RegCount` is also used extensively by X86Compiler's register allocator
      64             : //! and data structures. FP registers were omitted as they are never mapped to
      65             : //! variables, thus, not needed to be managed.
      66             : //!
      67             : //! NOTE: At the moment `X86RegCount` can fit into 32-bits, having 8-bits for
      68             : //! each register kind except FP. This can change in the future after a new
      69             : //! instruction set, which adds more registers, is introduced.
      70             : struct X86RegCount {
      71             :   // --------------------------------------------------------------------------
      72             :   // [Zero]
      73             :   // --------------------------------------------------------------------------
      74             : 
      75             :   //! Reset all counters to zero.
      76     1546003 :   ASMJIT_INLINE void reset() noexcept { _packed = 0; }
      77             : 
      78             :   // --------------------------------------------------------------------------
      79             :   // [Get]
      80             :   // --------------------------------------------------------------------------
      81             : 
      82             :   //! Get register count by a register `kind`.
      83             :   ASMJIT_INLINE uint32_t get(uint32_t kind) const noexcept {
      84             :     ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds);
      85             : 
      86             :     uint32_t shift = Utils::byteShiftOfDWordStruct(kind);
      87     8291219 :     return (_packed >> shift) & static_cast<uint32_t>(0xFF);
      88             :   }
      89             : 
      90             :   //! Get Gp count.
      91             :   ASMJIT_INLINE uint32_t getGp() const noexcept { return get(X86Reg::kKindGp); }
      92             :   //! Get Mm count.
      93             :   ASMJIT_INLINE uint32_t getMm() const noexcept { return get(X86Reg::kKindMm); }
      94             :   //! Get K count.
      95             :   ASMJIT_INLINE uint32_t getK() const noexcept { return get(X86Reg::kKindK); }
      96             :   //! Get XMM/YMM/ZMM count.
      97             :   ASMJIT_INLINE uint32_t getVec() const noexcept { return get(X86Reg::kKindVec); }
      98             : 
      99             :   // --------------------------------------------------------------------------
     100             :   // [Set]
     101             :   // --------------------------------------------------------------------------
     102             : 
     103             :   //! Set register count by a register `kind`.
     104             :   ASMJIT_INLINE void set(uint32_t kind, uint32_t n) noexcept {
     105             :     ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds);
     106             :     ASMJIT_ASSERT(n <= 0xFF);
     107             : 
     108             :     uint32_t shift = Utils::byteShiftOfDWordStruct(kind);
     109           0 :     _packed = (_packed & ~static_cast<uint32_t>(0xFF << shift)) + (n << shift);
     110           0 :   }
     111             : 
     112             :   //! Set Gp count.
     113             :   ASMJIT_INLINE void setGp(uint32_t n) noexcept { set(X86Reg::kKindGp, n); }
     114             :   //! Set Mm count.
     115             :   ASMJIT_INLINE void setMm(uint32_t n) noexcept { set(X86Reg::kKindMm, n); }
     116             :   //! Set K count.
     117             :   ASMJIT_INLINE void setK(uint32_t n) noexcept { set(X86Reg::kKindK, n); }
     118             :   //! Set XMM/YMM/ZMM count.
     119             :   ASMJIT_INLINE void setVec(uint32_t n) noexcept { set(X86Reg::kKindVec, n); }
     120             : 
     121             :   // --------------------------------------------------------------------------
     122             :   // [Add]
     123             :   // --------------------------------------------------------------------------
     124             : 
     125             :   //! Add register count by a register `kind`.
     126             :   ASMJIT_INLINE void add(uint32_t kind, uint32_t n = 1) noexcept {
     127             :     ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds);
     128             :     ASMJIT_ASSERT(0xFF - static_cast<uint32_t>(_regs[kind]) >= n);
     129             : 
     130             :     uint32_t shift = Utils::byteShiftOfDWordStruct(kind);
     131     1587154 :     _packed += n << shift;
     132      793577 :   }
     133             : 
     134             :   //! Add GP count.
     135             :   ASMJIT_INLINE void addGp(uint32_t n) noexcept { add(X86Reg::kKindGp, n); }
     136             :   //! Add MMX count.
     137             :   ASMJIT_INLINE void addMm(uint32_t n) noexcept { add(X86Reg::kKindMm, n); }
     138             :   //! Add K count.
     139             :   ASMJIT_INLINE void addK(uint32_t n) noexcept { add(X86Reg::kKindK, n); }
     140             :   //! Add XMM/YMM/ZMM count.
     141             :   ASMJIT_INLINE void addVec(uint32_t n) noexcept { add(X86Reg::kKindVec, n); }
     142             : 
     143             :   // --------------------------------------------------------------------------
     144             :   // [Misc]
     145             :   // --------------------------------------------------------------------------
     146             : 
     147             :   //! Build register indexes based on the given `count` of registers.
     148             :   ASMJIT_INLINE void indexFromRegCount(const X86RegCount& count) noexcept {
     149      493927 :     uint32_t x = static_cast<uint32_t>(count._regs[0]);
     150      493927 :     uint32_t y = static_cast<uint32_t>(count._regs[1]) + x;
     151      493927 :     uint32_t z = static_cast<uint32_t>(count._regs[2]) + y;
     152             : 
     153             :     ASMJIT_ASSERT(y <= 0xFF);
     154             :     ASMJIT_ASSERT(z <= 0xFF);
     155             :     _packed = Utils::pack32_4x8(0, x, y, z);
     156             :   }
     157             : 
     158             :   // --------------------------------------------------------------------------
     159             :   // [Members]
     160             :   // --------------------------------------------------------------------------
     161             : 
     162             :   union {
     163             :     struct {
     164             :       //! Count of GP registers.
     165             :       uint8_t _gp;
     166             :       //! Count of XMM|YMM|ZMM registers.
     167             :       uint8_t _vec;
     168             :       //! Count of MMX registers.
     169             :       uint8_t _mm;
     170             :       //! Count of K registers.
     171             :       uint8_t _k;
     172             :     };
     173             : 
     174             :     uint8_t _regs[4];
     175             :     uint32_t _packed;
     176             :   };
     177             : };
     178             : 
     179             : // ============================================================================
     180             : // [asmjit::X86RegMask]
     181             : // ============================================================================
     182             : 
     183             : //! \internal
     184             : //!
     185             : //! X86/X64 registers mask.
     186             : struct X86RegMask {
     187             :   // --------------------------------------------------------------------------
     188             :   // [Reset]
     189             :   // --------------------------------------------------------------------------
     190             : 
     191             :   //! Reset all register masks to zero.
     192             :   ASMJIT_INLINE void reset() noexcept {
     193             :     _packed.reset();
     194             :   }
     195             : 
     196             :   // --------------------------------------------------------------------------
     197             :   // [IsEmpty / Has]
     198             :   // --------------------------------------------------------------------------
     199             : 
     200             :   //! Get whether all register masks are zero (empty).
     201             :   ASMJIT_INLINE bool isEmpty() const noexcept {
     202             :     return _packed.isZero();
     203             :   }
     204             : 
     205             :   ASMJIT_INLINE bool has(uint32_t kind, uint32_t mask = 0xFFFFFFFFU) const noexcept {
     206             :     ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds);
     207             : 
     208           0 :     switch (kind) {
     209           0 :       case X86Reg::kKindGp : return (static_cast<uint32_t>(_gp ) & mask) != 0;
     210           0 :       case X86Reg::kKindVec: return (static_cast<uint32_t>(_vec) & mask) != 0;
     211           0 :       case X86Reg::kKindMm : return (static_cast<uint32_t>(_mm ) & mask) != 0;
     212           0 :       case X86Reg::kKindK  : return (static_cast<uint32_t>(_k  ) & mask) != 0;
     213             :     }
     214             : 
     215             :     return false;
     216             :   }
     217             : 
     218             :   ASMJIT_INLINE bool hasGp(uint32_t mask = 0xFFFFFFFFU) const noexcept { return has(X86Reg::kKindGp, mask); }
     219             :   ASMJIT_INLINE bool hasVec(uint32_t mask = 0xFFFFFFFFU) const noexcept { return has(X86Reg::kKindVec, mask); }
     220             :   ASMJIT_INLINE bool hasMm(uint32_t mask = 0xFFFFFFFFU) const noexcept { return has(X86Reg::kKindMm, mask); }
     221             :   ASMJIT_INLINE bool hasK(uint32_t mask = 0xFFFFFFFFU) const noexcept { return has(X86Reg::kKindK, mask); }
     222             : 
     223             :   // --------------------------------------------------------------------------
     224             :   // [Get]
     225             :   // --------------------------------------------------------------------------
     226             : 
     227             :   ASMJIT_INLINE uint32_t get(uint32_t kind) const noexcept {
     228             :     ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds);
     229             : 
     230      722394 :     switch (kind) {
     231     1271714 :       case X86Reg::kKindGp : return _gp;
     232     3446975 :       case X86Reg::kKindVec: return _vec;
     233      514304 :       case X86Reg::kKindMm : return _mm;
     234           0 :       case X86Reg::kKindK  : return _k;
     235             :     }
     236             : 
     237             :     return 0;
     238             :   }
     239             : 
     240             :   ASMJIT_INLINE uint32_t getGp() const noexcept { return get(X86Reg::kKindGp); }
     241             :   ASMJIT_INLINE uint32_t getVec() const noexcept { return get(X86Reg::kKindVec); }
     242             :   ASMJIT_INLINE uint32_t getMm() const noexcept { return get(X86Reg::kKindMm); }
     243             :   ASMJIT_INLINE uint32_t getK() const noexcept { return get(X86Reg::kKindK); }
     244             : 
     245             :   // --------------------------------------------------------------------------
     246             :   // [Zero]
     247             :   // --------------------------------------------------------------------------
     248             : 
     249             :   ASMJIT_INLINE void zero(uint32_t kind) noexcept {
     250             :     ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds);
     251             : 
     252             :     switch (kind) {
     253             :       case X86Reg::kKindGp : _gp  = 0; break;
     254             :       case X86Reg::kKindVec: _vec = 0; break;
     255             :       case X86Reg::kKindMm : _mm  = 0; break;
     256             :       case X86Reg::kKindK  : _k   = 0; break;
     257             :     }
     258             :   }
     259             : 
     260             :   ASMJIT_INLINE void zeroGp() noexcept { zero(X86Reg::kKindGp); }
     261             :   ASMJIT_INLINE void zeroVec() noexcept { zero(X86Reg::kKindVec); }
     262             :   ASMJIT_INLINE void zeroMm() noexcept { zero(X86Reg::kKindMm); }
     263             :   ASMJIT_INLINE void zeroK() noexcept { zero(X86Reg::kKindK); }
     264             : 
     265             :   // --------------------------------------------------------------------------
     266             :   // [Set]
     267             :   // --------------------------------------------------------------------------
     268             : 
     269             :   ASMJIT_INLINE void set(const X86RegMask& other) noexcept {
     270             :     _packed = other._packed;
     271             :   }
     272             : 
     273             :   ASMJIT_INLINE void set(uint32_t kind, uint32_t mask) noexcept {
     274             :     ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds);
     275             : 
     276             :     switch (kind) {
     277      215551 :       case X86Reg::kKindGp : _gp  = static_cast<uint16_t>(mask); break;
     278       26244 :       case X86Reg::kKindMm : _mm  = static_cast<uint8_t >(mask); break;
     279       13122 :       case X86Reg::kKindK  : _k   = static_cast<uint8_t >(mask); break;
     280      382574 :       case X86Reg::kKindVec: _vec = static_cast<uint32_t>(mask); break;
     281             :     }
     282             :   }
     283             : 
     284             :   ASMJIT_INLINE void setGp(uint32_t mask) noexcept { return set(X86Reg::kKindGp, mask); }
     285             :   ASMJIT_INLINE void setVec(uint32_t mask) noexcept { return set(X86Reg::kKindVec, mask); }
     286             :   ASMJIT_INLINE void setMm(uint32_t mask) noexcept { return set(X86Reg::kKindMm, mask); }
     287             :   ASMJIT_INLINE void setK(uint32_t mask) noexcept { return set(X86Reg::kKindK, mask); }
     288             : 
     289             :   // --------------------------------------------------------------------------
     290             :   // [And]
     291             :   // --------------------------------------------------------------------------
     292             : 
     293             :   ASMJIT_INLINE void and_(const X86RegMask& other) noexcept {
     294             :     _packed.and_(other._packed);
     295             :   }
     296             : 
     297             :   ASMJIT_INLINE void and_(uint32_t kind, uint32_t mask) noexcept {
     298             :     ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds);
     299             : 
     300             :     switch (kind) {
     301             :       case X86Reg::kKindGp : _gp  &= static_cast<uint16_t>(mask); break;
     302             :       case X86Reg::kKindMm : _mm  &= static_cast<uint8_t >(mask); break;
     303             :       case X86Reg::kKindK  : _k   &= static_cast<uint8_t >(mask); break;
     304             :       case X86Reg::kKindVec: _vec &= static_cast<uint32_t>(mask); break;
     305             :     }
     306             :   }
     307             : 
     308             :   ASMJIT_INLINE void andGp(uint32_t mask) noexcept { and_(X86Reg::kKindGp, mask); }
     309             :   ASMJIT_INLINE void andVec(uint32_t mask) noexcept { and_(X86Reg::kKindVec, mask); }
     310             :   ASMJIT_INLINE void andMm(uint32_t mask) noexcept { and_(X86Reg::kKindMm, mask); }
     311             :   ASMJIT_INLINE void andK(uint32_t mask) noexcept { and_(X86Reg::kKindK, mask); }
     312             : 
     313             :   // --------------------------------------------------------------------------
     314             :   // [AndNot]
     315             :   // --------------------------------------------------------------------------
     316             : 
     317             :   ASMJIT_INLINE void andNot(const X86RegMask& other) noexcept {
     318             :     _packed.andNot(other._packed);
     319             :   }
     320             : 
     321             :   ASMJIT_INLINE void andNot(uint32_t kind, uint32_t mask) noexcept {
     322             :     ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds);
     323             : 
     324             :     switch (kind) {
     325      105486 :       case X86Reg::kKindGp : _gp  &= ~static_cast<uint16_t>(mask); break;
     326           0 :       case X86Reg::kKindMm : _mm  &= ~static_cast<uint8_t >(mask); break;
     327             :       case X86Reg::kKindK  : _k   &= ~static_cast<uint8_t >(mask); break;
     328      256713 :       case X86Reg::kKindVec: _vec &= ~static_cast<uint32_t>(mask); break;
     329             :     }
     330             :   }
     331             : 
     332             :   ASMJIT_INLINE void andNotGp(uint32_t mask) noexcept { andNot(X86Reg::kKindGp, mask); }
     333             :   ASMJIT_INLINE void andNotVec(uint32_t mask) noexcept { andNot(X86Reg::kKindVec, mask); }
     334             :   ASMJIT_INLINE void andNotMm(uint32_t mask) noexcept { andNot(X86Reg::kKindMm, mask); }
     335             :   ASMJIT_INLINE void andNotK(uint32_t mask) noexcept { andNot(X86Reg::kKindK, mask); }
     336             : 
     337             :   // --------------------------------------------------------------------------
     338             :   // [Or]
     339             :   // --------------------------------------------------------------------------
     340             : 
     341             :   ASMJIT_INLINE void or_(const X86RegMask& other) noexcept {
     342             :     _packed.or_(other._packed);
     343      448694 :   }
     344             : 
     345             :   ASMJIT_INLINE void or_(uint32_t kind, uint32_t mask) noexcept {
     346             :     ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds);
     347       32111 :     switch (kind) {
     348      210972 :       case X86Reg::kKindGp : _gp  |= static_cast<uint16_t>(mask); break;
     349           0 :       case X86Reg::kKindMm : _mm  |= static_cast<uint8_t >(mask); break;
     350           0 :       case X86Reg::kKindK  : _k   |= static_cast<uint8_t >(mask); break;
     351      558374 :       case X86Reg::kKindVec: _vec |= static_cast<uint32_t>(mask); break;
     352             :     }
     353             :   }
     354             : 
     355             :   ASMJIT_INLINE void orGp(uint32_t mask) noexcept { return or_(X86Reg::kKindGp, mask); }
     356             :   ASMJIT_INLINE void orVec(uint32_t mask) noexcept { return or_(X86Reg::kKindVec, mask); }
     357             :   ASMJIT_INLINE void orMm(uint32_t mask) noexcept { return or_(X86Reg::kKindMm, mask); }
     358             :   ASMJIT_INLINE void orK(uint32_t mask) noexcept { return or_(X86Reg::kKindK, mask); }
     359             : 
     360             :   // --------------------------------------------------------------------------
     361             :   // [Xor]
     362             :   // --------------------------------------------------------------------------
     363             : 
     364             :   ASMJIT_INLINE void xor_(const X86RegMask& other) noexcept {
     365             :     _packed.xor_(other._packed);
     366             :   }
     367             : 
     368             :   ASMJIT_INLINE void xor_(uint32_t kind, uint32_t mask) noexcept {
     369             :     ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds);
     370             : 
     371           0 :     switch (kind) {
     372           0 :       case X86Reg::kKindGp : _gp  ^= static_cast<uint16_t>(mask); break;
     373           0 :       case X86Reg::kKindMm : _mm  ^= static_cast<uint8_t >(mask); break;
     374           0 :       case X86Reg::kKindK  : _k   ^= static_cast<uint8_t >(mask); break;
     375       66960 :       case X86Reg::kKindVec: _vec ^= static_cast<uint32_t>(mask); break;
     376             :     }
     377             :   }
     378             : 
     379             :   ASMJIT_INLINE void xorGp(uint32_t mask) noexcept { xor_(X86Reg::kKindGp, mask); }
     380             :   ASMJIT_INLINE void xorVec(uint32_t mask) noexcept { xor_(X86Reg::kKindVec, mask); }
     381             :   ASMJIT_INLINE void xorMm(uint32_t mask) noexcept { xor_(X86Reg::kKindMm, mask); }
     382             :   ASMJIT_INLINE void xorK(uint32_t mask) noexcept { xor_(X86Reg::kKindK, mask); }
     383             : 
     384             :   // --------------------------------------------------------------------------
     385             :   // [Members]
     386             :   // --------------------------------------------------------------------------
     387             : 
     388             :   union {
     389             :     struct {
     390             :       //! GP registers mask (16 bits).
     391             :       uint16_t _gp;
     392             :       //! MMX registers mask (8 bits).
     393             :       uint8_t _mm;
     394             :       //! K registers mask (8 bits).
     395             :       uint8_t _k;
     396             :       //! XMM|YMM|ZMM registers mask (32 bits).
     397             :       uint32_t _vec;
     398             :     };
     399             : 
     400             :     //! Packed masks.
     401             :     UInt64 _packed;
     402             :   };
     403             : };
     404             : 
     405             : //! \}
     406             : 
     407             : } // asmjit namespace
     408             : } // namespace PLMD
     409             : 
     410             : // [Api-End]
     411             : #include "./asmjit_apiend.h"
     412             : 
     413             : // [Guard]
     414             : #endif // _ASMJIT_X86_X86MISC_H
     415             : #pragma GCC diagnostic pop
     416             : #endif // __PLUMED_HAS_ASMJIT
     417             : #endif

Generated by: LCOV version 1.16