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. resetX86RegCount76 ASMJIT_INLINE void reset() noexcept { _packed = 0; } 77 78 // -------------------------------------------------------------------------- 79 // [Get] 80 // -------------------------------------------------------------------------- 81 82 //! Get register count by a register `kind`. getX86RegCount83 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 return (_packed >> shift) & static_cast<uint32_t>(0xFF); 88 } 89 90 //! Get Gp count. getGpX86RegCount91 ASMJIT_INLINE uint32_t getGp() const noexcept { return get(X86Reg::kKindGp); } 92 //! Get Mm count. getMmX86RegCount93 ASMJIT_INLINE uint32_t getMm() const noexcept { return get(X86Reg::kKindMm); } 94 //! Get K count. getKX86RegCount95 ASMJIT_INLINE uint32_t getK() const noexcept { return get(X86Reg::kKindK); } 96 //! Get XMM/YMM/ZMM count. getVecX86RegCount97 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`. setX86RegCount104 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 _packed = (_packed & ~static_cast<uint32_t>(0xFF << shift)) + (n << shift); 110 } 111 112 //! Set Gp count. setGpX86RegCount113 ASMJIT_INLINE void setGp(uint32_t n) noexcept { set(X86Reg::kKindGp, n); } 114 //! Set Mm count. setMmX86RegCount115 ASMJIT_INLINE void setMm(uint32_t n) noexcept { set(X86Reg::kKindMm, n); } 116 //! Set K count. setKX86RegCount117 ASMJIT_INLINE void setK(uint32_t n) noexcept { set(X86Reg::kKindK, n); } 118 //! Set XMM/YMM/ZMM count. setVecX86RegCount119 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 _packed += n << shift; 132 } 133 134 //! Add GP count. addGpX86RegCount135 ASMJIT_INLINE void addGp(uint32_t n) noexcept { add(X86Reg::kKindGp, n); } 136 //! Add MMX count. addMmX86RegCount137 ASMJIT_INLINE void addMm(uint32_t n) noexcept { add(X86Reg::kKindMm, n); } 138 //! Add K count. addKX86RegCount139 ASMJIT_INLINE void addK(uint32_t n) noexcept { add(X86Reg::kKindK, n); } 140 //! Add XMM/YMM/ZMM count. addVecX86RegCount141 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. indexFromRegCountX86RegCount148 ASMJIT_INLINE void indexFromRegCount(const X86RegCount& count) noexcept { 149 uint32_t x = static_cast<uint32_t>(count._regs[0]); 150 uint32_t y = static_cast<uint32_t>(count._regs[1]) + x; 151 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. resetX86RegMask192 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). isEmptyX86RegMask201 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 switch (kind) { 209 case X86Reg::kKindGp : return (static_cast<uint32_t>(_gp ) & mask) != 0; 210 case X86Reg::kKindVec: return (static_cast<uint32_t>(_vec) & mask) != 0; 211 case X86Reg::kKindMm : return (static_cast<uint32_t>(_mm ) & mask) != 0; 212 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 getX86RegMask227 ASMJIT_INLINE uint32_t get(uint32_t kind) const noexcept { 228 ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds); 229 230 switch (kind) { 231 case X86Reg::kKindGp : return _gp; 232 case X86Reg::kKindVec: return _vec; 233 case X86Reg::kKindMm : return _mm; 234 case X86Reg::kKindK : return _k; 235 } 236 237 return 0; 238 } 239 getGpX86RegMask240 ASMJIT_INLINE uint32_t getGp() const noexcept { return get(X86Reg::kKindGp); } getVecX86RegMask241 ASMJIT_INLINE uint32_t getVec() const noexcept { return get(X86Reg::kKindVec); } getMmX86RegMask242 ASMJIT_INLINE uint32_t getMm() const noexcept { return get(X86Reg::kKindMm); } getKX86RegMask243 ASMJIT_INLINE uint32_t getK() const noexcept { return get(X86Reg::kKindK); } 244 245 // -------------------------------------------------------------------------- 246 // [Zero] 247 // -------------------------------------------------------------------------- 248 zeroX86RegMask249 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 zeroGpX86RegMask260 ASMJIT_INLINE void zeroGp() noexcept { zero(X86Reg::kKindGp); } zeroVecX86RegMask261 ASMJIT_INLINE void zeroVec() noexcept { zero(X86Reg::kKindVec); } zeroMmX86RegMask262 ASMJIT_INLINE void zeroMm() noexcept { zero(X86Reg::kKindMm); } zeroKX86RegMask263 ASMJIT_INLINE void zeroK() noexcept { zero(X86Reg::kKindK); } 264 265 // -------------------------------------------------------------------------- 266 // [Set] 267 // -------------------------------------------------------------------------- 268 setX86RegMask269 ASMJIT_INLINE void set(const X86RegMask& other) noexcept { 270 _packed = other._packed; 271 } 272 setX86RegMask273 ASMJIT_INLINE void set(uint32_t kind, uint32_t mask) noexcept { 274 ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds); 275 276 switch (kind) { 277 case X86Reg::kKindGp : _gp = static_cast<uint16_t>(mask); break; 278 case X86Reg::kKindMm : _mm = static_cast<uint8_t >(mask); break; 279 case X86Reg::kKindK : _k = static_cast<uint8_t >(mask); break; 280 case X86Reg::kKindVec: _vec = static_cast<uint32_t>(mask); break; 281 } 282 } 283 setGpX86RegMask284 ASMJIT_INLINE void setGp(uint32_t mask) noexcept { return set(X86Reg::kKindGp, mask); } setVecX86RegMask285 ASMJIT_INLINE void setVec(uint32_t mask) noexcept { return set(X86Reg::kKindVec, mask); } setMmX86RegMask286 ASMJIT_INLINE void setMm(uint32_t mask) noexcept { return set(X86Reg::kKindMm, mask); } setKX86RegMask287 ASMJIT_INLINE void setK(uint32_t mask) noexcept { return set(X86Reg::kKindK, mask); } 288 289 // -------------------------------------------------------------------------- 290 // [And] 291 // -------------------------------------------------------------------------- 292 and_X86RegMask293 ASMJIT_INLINE void and_(const X86RegMask& other) noexcept { 294 _packed.and_(other._packed); 295 } 296 and_X86RegMask297 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 andGpX86RegMask308 ASMJIT_INLINE void andGp(uint32_t mask) noexcept { and_(X86Reg::kKindGp, mask); } andVecX86RegMask309 ASMJIT_INLINE void andVec(uint32_t mask) noexcept { and_(X86Reg::kKindVec, mask); } andMmX86RegMask310 ASMJIT_INLINE void andMm(uint32_t mask) noexcept { and_(X86Reg::kKindMm, mask); } andKX86RegMask311 ASMJIT_INLINE void andK(uint32_t mask) noexcept { and_(X86Reg::kKindK, mask); } 312 313 // -------------------------------------------------------------------------- 314 // [AndNot] 315 // -------------------------------------------------------------------------- 316 andNotX86RegMask317 ASMJIT_INLINE void andNot(const X86RegMask& other) noexcept { 318 _packed.andNot(other._packed); 319 } 320 andNotX86RegMask321 ASMJIT_INLINE void andNot(uint32_t kind, uint32_t mask) noexcept { 322 ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds); 323 324 switch (kind) { 325 case X86Reg::kKindGp : _gp &= ~static_cast<uint16_t>(mask); break; 326 case X86Reg::kKindMm : _mm &= ~static_cast<uint8_t >(mask); break; 327 case X86Reg::kKindK : _k &= ~static_cast<uint8_t >(mask); break; 328 case X86Reg::kKindVec: _vec &= ~static_cast<uint32_t>(mask); break; 329 } 330 } 331 andNotGpX86RegMask332 ASMJIT_INLINE void andNotGp(uint32_t mask) noexcept { andNot(X86Reg::kKindGp, mask); } andNotVecX86RegMask333 ASMJIT_INLINE void andNotVec(uint32_t mask) noexcept { andNot(X86Reg::kKindVec, mask); } andNotMmX86RegMask334 ASMJIT_INLINE void andNotMm(uint32_t mask) noexcept { andNot(X86Reg::kKindMm, mask); } andNotKX86RegMask335 ASMJIT_INLINE void andNotK(uint32_t mask) noexcept { andNot(X86Reg::kKindK, mask); } 336 337 // -------------------------------------------------------------------------- 338 // [Or] 339 // -------------------------------------------------------------------------- 340 or_X86RegMask341 ASMJIT_INLINE void or_(const X86RegMask& other) noexcept { 342 _packed.or_(other._packed); 343 } 344 or_X86RegMask345 ASMJIT_INLINE void or_(uint32_t kind, uint32_t mask) noexcept { 346 ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds); 347 switch (kind) { 348 case X86Reg::kKindGp : _gp |= static_cast<uint16_t>(mask); break; 349 case X86Reg::kKindMm : _mm |= static_cast<uint8_t >(mask); break; 350 case X86Reg::kKindK : _k |= static_cast<uint8_t >(mask); break; 351 case X86Reg::kKindVec: _vec |= static_cast<uint32_t>(mask); break; 352 } 353 } 354 orGpX86RegMask355 ASMJIT_INLINE void orGp(uint32_t mask) noexcept { return or_(X86Reg::kKindGp, mask); } orVecX86RegMask356 ASMJIT_INLINE void orVec(uint32_t mask) noexcept { return or_(X86Reg::kKindVec, mask); } orMmX86RegMask357 ASMJIT_INLINE void orMm(uint32_t mask) noexcept { return or_(X86Reg::kKindMm, mask); } orKX86RegMask358 ASMJIT_INLINE void orK(uint32_t mask) noexcept { return or_(X86Reg::kKindK, mask); } 359 360 // -------------------------------------------------------------------------- 361 // [Xor] 362 // -------------------------------------------------------------------------- 363 xor_X86RegMask364 ASMJIT_INLINE void xor_(const X86RegMask& other) noexcept { 365 _packed.xor_(other._packed); 366 } 367 xor_X86RegMask368 ASMJIT_INLINE void xor_(uint32_t kind, uint32_t mask) noexcept { 369 ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds); 370 371 switch (kind) { 372 case X86Reg::kKindGp : _gp ^= static_cast<uint16_t>(mask); break; 373 case X86Reg::kKindMm : _mm ^= static_cast<uint8_t >(mask); break; 374 case X86Reg::kKindK : _k ^= static_cast<uint8_t >(mask); break; 375 case X86Reg::kKindVec: _vec ^= static_cast<uint32_t>(mask); break; 376 } 377 } 378 xorGpX86RegMask379 ASMJIT_INLINE void xorGp(uint32_t mask) noexcept { xor_(X86Reg::kKindGp, mask); } xorVecX86RegMask380 ASMJIT_INLINE void xorVec(uint32_t mask) noexcept { xor_(X86Reg::kKindVec, mask); } xorMmX86RegMask381 ASMJIT_INLINE void xorMm(uint32_t mask) noexcept { xor_(X86Reg::kKindMm, mask); } xorKX86RegMask382 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 418