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 113778 : 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 572782 : 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 122748 : _packed += n << shift;
132 61374 : }
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 36630 : uint32_t x = static_cast<uint32_t>(count._regs[0]);
150 36630 : uint32_t y = static_cast<uint32_t>(count._regs[1]) + x;
151 36630 : 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 54712 : switch (kind) {
231 95434 : case X86Reg::kKindGp : return _gp;
232 214776 : case X86Reg::kKindVec: return _vec;
233 41230 : 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 16588 : case X86Reg::kKindGp : _gp = static_cast<uint16_t>(mask); break;
278 3272 : case X86Reg::kKindMm : _mm = static_cast<uint8_t >(mask); break;
279 1636 : case X86Reg::kKindK : _k = static_cast<uint8_t >(mask); break;
280 30710 : 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 7248 : 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 22440 : 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 33050 : }
344 :
345 : ASMJIT_INLINE void or_(uint32_t kind, uint32_t mask) noexcept {
346 : ASMJIT_ASSERT(kind < Globals::kMaxVRegKinds);
347 1944 : switch (kind) {
348 14496 : 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 42860 : 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 5080 : 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
|