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_utils_h
21 : #define __PLUMED_asmjit_utils_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_BASE_UTILS_H
33 : #define _ASMJIT_BASE_UTILS_H
34 :
35 : // [Dependencies]
36 : #include "./globals.h"
37 :
38 : #if ASMJIT_CC_MSC_GE(14, 0, 0)
39 : # include <intrin.h>
40 : #endif // ASMJIT_OS_WINDOWS
41 :
42 : // [Api-Begin]
43 : #include "./asmjit_apibegin.h"
44 :
45 : namespace PLMD {
46 : namespace asmjit {
47 :
48 : //! \addtogroup asmjit_base
49 : //! \{
50 :
51 : // ============================================================================
52 : // [asmjit::IntTraits]
53 : // ============================================================================
54 :
55 : //! \internal
56 : //! \{
57 : template<size_t Size, int IsSigned>
58 : struct IntTraitsPrivate {}; // Let it fail if not specialized!
59 :
60 : template<> struct IntTraitsPrivate<1, 0> { typedef int IntType; typedef int8_t SignedType; typedef uint8_t UnsignedType; };
61 : template<> struct IntTraitsPrivate<1, 1> { typedef int IntType; typedef int8_t SignedType; typedef uint8_t UnsignedType; };
62 :
63 : template<> struct IntTraitsPrivate<2, 0> { typedef int IntType; typedef int16_t SignedType; typedef uint16_t UnsignedType; };
64 : template<> struct IntTraitsPrivate<2, 1> { typedef int IntType; typedef int16_t SignedType; typedef uint16_t UnsignedType; };
65 :
66 : template<> struct IntTraitsPrivate<4, 0> { typedef int64_t IntType; typedef int32_t SignedType; typedef uint32_t UnsignedType; };
67 : template<> struct IntTraitsPrivate<4, 1> { typedef int IntType; typedef int32_t SignedType; typedef uint32_t UnsignedType; };
68 :
69 : template<> struct IntTraitsPrivate<8, 0> { typedef int64_t IntType; typedef int64_t SignedType; typedef uint64_t UnsignedType; };
70 : template<> struct IntTraitsPrivate<8, 1> { typedef int64_t IntType; typedef int64_t SignedType; typedef uint64_t UnsignedType; };
71 :
72 : //! \internal
73 : template<typename T>
74 : struct IntTraits {
75 : enum {
76 : kIsSigned = static_cast<T>(~static_cast<T>(0)) < static_cast<T>(0),
77 : kIsUnsigned = !kIsSigned,
78 : kIs8Bit = sizeof(T) == 1,
79 : kIs16Bit = sizeof(T) == 2,
80 : kIs32Bit = sizeof(T) == 4,
81 : kIs64Bit = sizeof(T) == 8,
82 : kIsIntPtr = sizeof(T) == sizeof(intptr_t)
83 : };
84 :
85 : typedef typename IntTraitsPrivate<sizeof(T), kIsSigned>::IntType IntType;
86 : typedef typename IntTraitsPrivate<sizeof(T), kIsSigned>::SignedType SignedType;
87 : typedef typename IntTraitsPrivate<sizeof(T), kIsSigned>::UnsignedType UnsignedType;
88 :
89 : //! Get a minimum value of `T`.
90 : static ASMJIT_INLINE T minValue() noexcept {
91 : return kIsSigned ? T((~static_cast<UnsignedType>(0) >> 1) + static_cast<UnsignedType>(1)) : T(0);
92 : }
93 :
94 : //! Get a maximum value of `T`.
95 : static ASMJIT_INLINE T maxValue() noexcept {
96 : return kIsSigned ? T(~static_cast<UnsignedType>(0) >> 1) : ~T(0);
97 : }
98 : };
99 :
100 : //! \}
101 :
102 : // ============================================================================
103 : // [asmjit::Utils]
104 : // ============================================================================
105 :
106 : //! AsmJit utilities - integer, string, etc...
107 : namespace Utils {
108 : // --------------------------------------------------------------------------
109 : // [Float <-> Int]
110 : // --------------------------------------------------------------------------
111 :
112 : //! \internal
113 : union FloatBits {
114 : int32_t i;
115 : float f;
116 : };
117 :
118 : //! \internal
119 : union DoubleBits {
120 : int64_t i;
121 : double d;
122 : };
123 :
124 : //! Bit-cast `float` to a 32-bit integer.
125 : static ASMJIT_INLINE int32_t floatAsInt(float f) noexcept { FloatBits m; m.f = f; return m.i; }
126 : //! Bit-cast 32-bit integer to `float`.
127 : static ASMJIT_INLINE float intAsFloat(int32_t i) noexcept { FloatBits m; m.i = i; return m.f; }
128 :
129 : //! Bit-cast `double` to a 64-bit integer.
130 : static ASMJIT_INLINE int64_t doubleAsInt(double d) noexcept { DoubleBits m; m.d = d; return m.i; }
131 : //! Bit-cast 64-bit integer to `double`.
132 : static ASMJIT_INLINE double intAsDouble(int64_t i) noexcept { DoubleBits m; m.i = i; return m.d; }
133 :
134 : // --------------------------------------------------------------------------
135 : // [Pack / Unpack]
136 : // --------------------------------------------------------------------------
137 :
138 : //! Pack four 8-bit integer into a 32-bit integer as it is an array of `{b0,b1,b2,b3}`.
139 : static ASMJIT_INLINE uint32_t pack32_4x8(uint32_t b0, uint32_t b1, uint32_t b2, uint32_t b3) noexcept {
140 493927 : return ASMJIT_PACK32_4x8(b0, b1, b2, b3);
141 : }
142 :
143 : //! Pack two 32-bit integer into a 64-bit integer as it is an array of `{u0,u1}`.
144 : static ASMJIT_INLINE uint64_t pack64_2x32(uint32_t u0, uint32_t u1) noexcept {
145 625107 : return ASMJIT_ARCH_LE ? (static_cast<uint64_t>(u1) << 32) + u0
146 382034 : : (static_cast<uint64_t>(u0) << 32) + u1;
147 : }
148 :
149 : // --------------------------------------------------------------------------
150 : // [Position of byte (in bit-shift)]
151 : // --------------------------------------------------------------------------
152 :
153 : static ASMJIT_INLINE uint32_t byteShiftOfDWordStruct(uint32_t index) noexcept {
154 : if (ASMJIT_ARCH_LE)
155 1587154 : return index * 8;
156 : else
157 : return (sizeof(uint32_t) - 1 - index) * 8;
158 : }
159 :
160 : // --------------------------------------------------------------------------
161 : // [Lower/Upper]
162 : // --------------------------------------------------------------------------
163 :
164 : template<typename T>
165 : static ASMJIT_INLINE T toLower(T c) noexcept { return c ^ (static_cast<T>(c >= T('A') && c <= T('Z')) << 5); }
166 : template<typename T>
167 : static ASMJIT_INLINE T toUpper(T c) noexcept { return c ^ (static_cast<T>(c >= T('a') && c <= T('z')) << 5); }
168 :
169 : // --------------------------------------------------------------------------
170 : // [Hash]
171 : // --------------------------------------------------------------------------
172 :
173 : // \internal
174 0 : static ASMJIT_INLINE uint32_t hashRound(uint32_t hash, uint32_t c) noexcept { return hash * 65599 + c; }
175 :
176 : // Get a hash of the given string `str` of `len` length. Length must be valid
177 : // as this function doesn't check for a null terminator and allows it in the
178 : // middle of the string.
179 : static ASMJIT_INLINE uint32_t hashString(const char* str, size_t len) noexcept {
180 : uint32_t hVal = 0;
181 : for (uint32_t i = 0; i < len; i++)
182 : hVal = hashRound(hVal, str[i]);
183 : return hVal;
184 : }
185 :
186 : // --------------------------------------------------------------------------
187 : // [Swap]
188 : // --------------------------------------------------------------------------
189 :
190 : template<typename T>
191 : static ASMJIT_INLINE void swap(T& a, T& b) noexcept {
192 : T tmp = a;
193 : a = b;
194 : b = tmp;
195 : }
196 :
197 : // --------------------------------------------------------------------------
198 : // [InInterval]
199 : // --------------------------------------------------------------------------
200 :
201 : //! Get whether `x` is greater than or equal to `a` and lesses than or equal to `b`.
202 : template<typename T>
203 : static ASMJIT_INLINE bool inInterval(T x, T a, T b) noexcept {
204 231176 : return x >= a && x <= b;
205 : }
206 :
207 : // --------------------------------------------------------------------------
208 : // [AsInt]
209 : // --------------------------------------------------------------------------
210 :
211 : //! Map an integer `x` of type `T` to `int` or `int64_t` depending on the
212 : //! type. Used internally by AsmJit to dispatch arguments that can be of
213 : //! arbitrary integer type into a function argument that is either `int` or
214 : //! `int64_t`.
215 : template<typename T>
216 : static ASMJIT_INLINE typename IntTraits<T>::IntType asInt(T x) noexcept {
217 4712 : return static_cast<typename IntTraits<T>::IntType>(x);
218 : }
219 :
220 : // --------------------------------------------------------------------------
221 : // [IsInt / IsUInt]
222 : // --------------------------------------------------------------------------
223 :
224 : //! Get whether the given integer `x` can be casted to a 4-bit signed integer.
225 : template<typename T>
226 : static ASMJIT_INLINE bool isInt4(T x) noexcept {
227 : typedef typename IntTraits<T>::SignedType SignedType;
228 : typedef typename IntTraits<T>::UnsignedType UnsignedType;
229 :
230 : if (IntTraits<T>::kIsSigned)
231 : return inInterval<SignedType>(SignedType(x), -8, 7);
232 : else
233 : return UnsignedType(x) <= UnsignedType(7U);
234 : }
235 :
236 : //! Get whether the given integer `x` can be casted to an 8-bit signed integer.
237 : template<typename T>
238 : static ASMJIT_INLINE bool isInt8(T x) noexcept {
239 : typedef typename IntTraits<T>::SignedType SignedType;
240 : typedef typename IntTraits<T>::UnsignedType UnsignedType;
241 :
242 : if (IntTraits<T>::kIsSigned)
243 : return sizeof(T) <= 1 || inInterval<SignedType>(SignedType(x), -128, 127);
244 : else
245 : return UnsignedType(x) <= UnsignedType(127U);
246 : }
247 :
248 : //! Get whether the given integer `x` can be casted to a 16-bit signed integer.
249 : template<typename T>
250 : static ASMJIT_INLINE bool isInt16(T x) noexcept {
251 : typedef typename IntTraits<T>::SignedType SignedType;
252 : typedef typename IntTraits<T>::UnsignedType UnsignedType;
253 :
254 : if (IntTraits<T>::kIsSigned)
255 : return sizeof(T) <= 2 || inInterval<SignedType>(SignedType(x), -32768, 32767);
256 : else
257 : return sizeof(T) <= 1 || UnsignedType(x) <= UnsignedType(32767U);
258 : }
259 :
260 : //! Get whether the given integer `x` can be casted to a 32-bit signed integer.
261 : template<typename T>
262 : static ASMJIT_INLINE bool isInt32(T x) noexcept {
263 : typedef typename IntTraits<T>::SignedType SignedType;
264 : typedef typename IntTraits<T>::UnsignedType UnsignedType;
265 :
266 : if (IntTraits<T>::kIsSigned)
267 : return sizeof(T) <= 4 || inInterval<SignedType>(SignedType(x), -2147483647 - 1, 2147483647);
268 : else
269 : return sizeof(T) <= 2 || UnsignedType(x) <= UnsignedType(2147483647U);
270 : }
271 :
272 : //! Get whether the given integer `x` can be casted to a 4-bit unsigned integer.
273 : template<typename T>
274 : static ASMJIT_INLINE bool isUInt4(T x) noexcept {
275 : typedef typename IntTraits<T>::UnsignedType UnsignedType;
276 :
277 : if (IntTraits<T>::kIsSigned)
278 : return x >= T(0) && x <= T(15);
279 : else
280 : return UnsignedType(x) <= UnsignedType(15U);
281 : }
282 :
283 : //! Get whether the given integer `x` can be casted to an 8-bit unsigned integer.
284 : template<typename T>
285 : static ASMJIT_INLINE bool isUInt8(T x) noexcept {
286 : typedef typename IntTraits<T>::UnsignedType UnsignedType;
287 :
288 : if (IntTraits<T>::kIsSigned)
289 : return x >= T(0) && (sizeof(T) <= 1 ? true : x <= T(255));
290 : else
291 : return sizeof(T) <= 1 || UnsignedType(x) <= UnsignedType(255U);
292 : }
293 :
294 : //! Get whether the given integer `x` can be casted to a 12-bit unsigned integer (ARM specific).
295 : template<typename T>
296 : static ASMJIT_INLINE bool isUInt12(T x) noexcept {
297 : typedef typename IntTraits<T>::UnsignedType UnsignedType;
298 :
299 : if (IntTraits<T>::kIsSigned)
300 : return x >= T(0) && (sizeof(T) <= 1 ? true : x <= T(4095));
301 : else
302 : return sizeof(T) <= 1 || UnsignedType(x) <= UnsignedType(4095U);
303 : }
304 :
305 : //! Get whether the given integer `x` can be casted to a 16-bit unsigned integer.
306 : template<typename T>
307 : static ASMJIT_INLINE bool isUInt16(T x) noexcept {
308 : typedef typename IntTraits<T>::UnsignedType UnsignedType;
309 :
310 : if (IntTraits<T>::kIsSigned)
311 : return x >= T(0) && (sizeof(T) <= 2 ? true : x <= T(65535));
312 : else
313 : return sizeof(T) <= 2 || UnsignedType(x) <= UnsignedType(65535U);
314 : }
315 :
316 : //! Get whether the given integer `x` can be casted to a 32-bit unsigned integer.
317 : template<typename T>
318 : static ASMJIT_INLINE bool isUInt32(T x) noexcept {
319 : typedef typename IntTraits<T>::UnsignedType UnsignedType;
320 :
321 : if (IntTraits<T>::kIsSigned)
322 116534 : return x >= T(0) && (sizeof(T) <= 4 ? true : x <= T(4294967295U));
323 : else
324 : return sizeof(T) <= 4 || UnsignedType(x) <= UnsignedType(4294967295U);
325 : }
326 :
327 : // --------------------------------------------------------------------------
328 : // [IsPowerOf2]
329 : // --------------------------------------------------------------------------
330 :
331 : //! Get whether the `n` value is a power of two (only one bit is set).
332 : template<typename T>
333 : static ASMJIT_INLINE bool isPowerOf2(T n) noexcept {
334 368292 : return n != 0 && (n & (n - 1)) == 0;
335 : }
336 :
337 : // --------------------------------------------------------------------------
338 : // [Mask]
339 : // --------------------------------------------------------------------------
340 :
341 : //! Generate a bit-mask that has `x` bit set.
342 : static ASMJIT_INLINE uint32_t mask(uint32_t x) noexcept {
343 : ASMJIT_ASSERT(x < 32);
344 2039306 : return static_cast<uint32_t>(1) << x;
345 : }
346 :
347 : //! Generate a bit-mask that has `x0` and `x1` bits set.
348 : static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1) noexcept {
349 : return mask(x0) | mask(x1);
350 : }
351 :
352 : //! Generate a bit-mask that has `x0`, `x1` and `x2` bits set.
353 : static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2) noexcept {
354 : return mask(x0, x1) | mask(x2);
355 : }
356 :
357 : //! Generate a bit-mask that has `x0`, `x1`, `x2` and `x3` bits set.
358 : static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3) noexcept {
359 : return mask(x0, x1) | mask(x2, x3);
360 : }
361 :
362 : //! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3` and `x4` bits set.
363 : static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4) noexcept {
364 : return mask(x0, x1) | mask(x2, x3) | mask(x4);
365 : }
366 :
367 : //! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4` and `x5` bits set.
368 : static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5) noexcept {
369 : return mask(x0, x1) | mask(x2, x3) | mask(x4, x5);
370 : }
371 :
372 : //! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5` and `x6` bits set.
373 : static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6) noexcept {
374 : return mask(x0, x1) | mask(x2, x3) | mask(x4, x5) | mask(x6);
375 : }
376 :
377 : //! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6` and `x7` bits set.
378 : static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7) noexcept {
379 : return mask(x0, x1) | mask(x2, x3) | mask(x4, x5) | mask(x6, x7);
380 : }
381 :
382 : //! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6`, `x7` and `x8` bits set.
383 : static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7, uint32_t x8) noexcept {
384 : return mask(x0, x1) | mask(x2, x3) | mask(x4, x5) | mask(x6, x7) | mask(x8);
385 : }
386 :
387 : //! Generate a bit-mask that has `x0`, `x1`, `x2`, `x3`, `x4`, `x5`, `x6`, `x7`, `x8` and `x9` bits set.
388 : static ASMJIT_INLINE uint32_t mask(uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3, uint32_t x4, uint32_t x5, uint32_t x6, uint32_t x7, uint32_t x8, uint32_t x9) noexcept {
389 : return mask(x0, x1) | mask(x2, x3) | mask(x4, x5) | mask(x6, x7) | mask(x8, x9);
390 : }
391 :
392 : // --------------------------------------------------------------------------
393 : // [Bits]
394 : // --------------------------------------------------------------------------
395 :
396 : //! Generate a bit-mask that has `x` least significant bits set.
397 : static ASMJIT_INLINE uint32_t bits(uint32_t x) noexcept {
398 : // Shifting more bits than the type has results in undefined behavior. In
399 : // such case asmjit trashes the result by ORing with `overflow` mask, which
400 : // discards the undefined value returned by the shift.
401 77344 : uint32_t overflow = static_cast<uint32_t>(
402 77344 : -static_cast<int32_t>(x >= sizeof(uint32_t) * 8));
403 :
404 77344 : return ((static_cast<uint32_t>(1) << x) - 1U) | overflow;
405 : }
406 :
407 : // --------------------------------------------------------------------------
408 : // [HasBit]
409 : // --------------------------------------------------------------------------
410 :
411 : //! Get whether `x` has bit `n` set.
412 : template<typename T, typename Index>
413 : static ASMJIT_INLINE bool hasBit(T x, Index n) noexcept {
414 : return (x & (static_cast<T>(1) << n)) != 0;
415 : }
416 :
417 : // --------------------------------------------------------------------------
418 : // [BitCount]
419 : // --------------------------------------------------------------------------
420 :
421 : static ASMJIT_INLINE uint32_t bitCountSlow(uint32_t x) noexcept {
422 : // From: http://graphics.stanford.edu/~seander/bithacks.html
423 : x = x - ((x >> 1) & 0x55555555U);
424 : x = (x & 0x33333333U) + ((x >> 2) & 0x33333333U);
425 : return (((x + (x >> 4)) & 0x0F0F0F0FU) * 0x01010101U) >> 24;
426 : }
427 :
428 : //! Get count of bits in `x`.
429 : static ASMJIT_INLINE uint32_t bitCount(uint32_t x) noexcept {
430 : #if ASMJIT_CC_GCC || ASMJIT_CC_CLANG
431 32111 : return __builtin_popcount(x);
432 : #else
433 : return bitCountSlow(x);
434 : #endif
435 : }
436 :
437 : // --------------------------------------------------------------------------
438 : // [FirstBitOf]
439 : // --------------------------------------------------------------------------
440 :
441 : template<uint64_t In>
442 : struct FirstBitOfTImpl {
443 : enum {
444 : _shift = (In & ASMJIT_UINT64_C(0x0000FFFFFFFFFFFF)) == 0 ? 48 :
445 : (In & ASMJIT_UINT64_C(0x00000000FFFFFFFF)) == 0 ? 32 :
446 : (In & ASMJIT_UINT64_C(0x000000000000FFFF)) == 0 ? 16 : 0,
447 :
448 : kValue = ((In >> _shift) & 0x0001) ? (_shift + 0) :
449 : ((In >> _shift) & 0x0002) ? (_shift + 1) :
450 : ((In >> _shift) & 0x0004) ? (_shift + 2) :
451 : ((In >> _shift) & 0x0008) ? (_shift + 3) :
452 : ((In >> _shift) & 0x0010) ? (_shift + 4) :
453 : ((In >> _shift) & 0x0020) ? (_shift + 5) :
454 : ((In >> _shift) & 0x0040) ? (_shift + 6) :
455 : ((In >> _shift) & 0x0080) ? (_shift + 7) :
456 : ((In >> _shift) & 0x0100) ? (_shift + 8) :
457 : ((In >> _shift) & 0x0200) ? (_shift + 9) :
458 : ((In >> _shift) & 0x0400) ? (_shift + 10) :
459 : ((In >> _shift) & 0x0800) ? (_shift + 11) :
460 : ((In >> _shift) & 0x1000) ? (_shift + 12) :
461 : ((In >> _shift) & 0x2000) ? (_shift + 13) :
462 : ((In >> _shift) & 0x4000) ? (_shift + 14) :
463 : ((In >> _shift) & 0x8000) ? (_shift + 15) : 0
464 : };
465 : };
466 :
467 : template<>
468 : struct FirstBitOfTImpl<0> {};
469 :
470 : template<uint64_t In>
471 : static ASMJIT_INLINE uint32_t firstBitOfT() noexcept { return FirstBitOfTImpl<In>::kValue; }
472 :
473 : // --------------------------------------------------------------------------
474 : // [FindFirstBit]
475 : // --------------------------------------------------------------------------
476 :
477 : //! \internal
478 : static ASMJIT_INLINE uint32_t findFirstBitSlow(uint32_t mask) noexcept {
479 : // This is a reference (slow) implementation of `findFirstBit()`, used when
480 : // we don't have a C++ compiler support. The implementation speed has been
481 : // improved to check for 2 bits per iteration.
482 : uint32_t i = 1;
483 :
484 : while (mask != 0) {
485 : uint32_t two = mask & 0x3;
486 : if (two != 0x0)
487 : return i - (two & 0x1);
488 :
489 : i += 2;
490 : mask >>= 2;
491 : }
492 :
493 : return 0xFFFFFFFFU;
494 : }
495 :
496 : //! Find a first bit in `mask`.
497 : static ASMJIT_INLINE uint32_t findFirstBit(uint32_t mask) noexcept {
498 : #if ASMJIT_CC_MSC_GE(14, 0, 0) && (ASMJIT_ARCH_X86 || ASMJIT_ARCH_ARM32 || \
499 : ASMJIT_ARCH_X64 || ASMJIT_ARCH_ARM64)
500 : DWORD i;
501 : if (_BitScanForward(&i, mask))
502 : return static_cast<uint32_t>(i);
503 : else
504 : return 0xFFFFFFFFU;
505 : #elif ASMJIT_CC_GCC_GE(3, 4, 6) || ASMJIT_CC_CLANG
506 420127 : if (mask)
507 420127 : return __builtin_ctz(mask);
508 : else
509 : return 0xFFFFFFFFU;
510 : #else
511 : return findFirstBitSlow(mask);
512 : #endif
513 : }
514 :
515 : // --------------------------------------------------------------------------
516 : // [Misc]
517 : // --------------------------------------------------------------------------
518 :
519 : static ASMJIT_INLINE uint32_t keepNOnesFromRight(uint32_t mask, uint32_t nBits) noexcept {
520 : uint32_t m = 0x1;
521 :
522 : do {
523 : nBits -= (mask & m) != 0;
524 : m <<= 1;
525 : if (nBits == 0) {
526 : m -= 1;
527 : mask &= m;
528 : break;
529 : }
530 : } while (m);
531 :
532 : return mask;
533 : }
534 :
535 : static ASMJIT_INLINE uint32_t indexNOnesFromRight(uint8_t* dst, uint32_t mask, uint32_t nBits) noexcept {
536 : uint32_t totalBits = nBits;
537 : uint8_t i = 0;
538 : uint32_t m = 0x1;
539 :
540 : do {
541 : if (mask & m) {
542 : *dst++ = i;
543 : if (--nBits == 0)
544 : break;
545 : }
546 :
547 : m <<= 1;
548 : i++;
549 : } while (m);
550 :
551 : return totalBits - nBits;
552 : }
553 :
554 : // --------------------------------------------------------------------------
555 : // [Alignment]
556 : // --------------------------------------------------------------------------
557 :
558 : template<typename X, typename Y>
559 : static ASMJIT_INLINE bool isAligned(X base, Y alignment) noexcept {
560 : typedef typename IntTraitsPrivate<sizeof(X), 0>::UnsignedType U;
561 0 : return ((U)base % (U)alignment) == 0;
562 : }
563 :
564 : template<typename X, typename Y>
565 : static ASMJIT_INLINE X alignTo(X x, Y alignment) noexcept {
566 : typedef typename IntTraitsPrivate<sizeof(X), 0>::UnsignedType U;
567 2351722 : return (X)( ((U)x + (U)(alignment - 1)) & ~(static_cast<U>(alignment) - 1) );
568 : }
569 :
570 : //! Get delta required to align `base` to `alignment`.
571 : template<typename X, typename Y>
572 : static ASMJIT_INLINE X alignDiff(X base, Y alignment) noexcept {
573 7106 : return alignTo(base, alignment) - base;
574 : }
575 :
576 : template<typename T>
577 : static ASMJIT_INLINE T alignToPowerOf2(T base) noexcept {
578 : // Implementation is from "Hacker's Delight" by Henry S. Warren, Jr.
579 : base -= 1;
580 :
581 : #if defined(_MSC_VER)
582 : # pragma warning(push)
583 : # pragma warning(disable: 4293)
584 : #endif // _MSC_VER
585 :
586 : base = base | (base >> 1);
587 : base = base | (base >> 2);
588 : base = base | (base >> 4);
589 :
590 : // 8/16/32 constants are multiplied by the condition to prevent a compiler
591 : // complaining about the 'shift count >= type width' (GCC).
592 : if (sizeof(T) >= 2) base = base | (base >> ( 8 * (sizeof(T) >= 2))); // Base >> 8.
593 : if (sizeof(T) >= 4) base = base | (base >> (16 * (sizeof(T) >= 4))); // Base >> 16.
594 : if (sizeof(T) >= 8) base = base | (base >> (32 * (sizeof(T) >= 8))); // Base >> 32.
595 :
596 : #if defined(_MSC_VER)
597 : # pragma warning(pop)
598 : #endif // _MSC_VER
599 :
600 : return base + 1;
601 : }
602 :
603 : // --------------------------------------------------------------------------
604 : // [String]
605 : // --------------------------------------------------------------------------
606 :
607 : static ASMJIT_INLINE size_t strLen(const char* s, size_t maxlen) noexcept {
608 : size_t i;
609 0 : for (i = 0; i < maxlen; i++)
610 0 : if (!s[i])
611 : break;
612 : return i;
613 : }
614 :
615 : static ASMJIT_INLINE const char* findPackedString(const char* p, uint32_t id) noexcept {
616 : uint32_t i = 0;
617 0 : while (i < id) {
618 0 : while (p[0])
619 0 : p++;
620 0 : p++;
621 0 : i++;
622 : }
623 : return p;
624 : }
625 :
626 : //! \internal
627 : //!
628 : //! Compare two instruction names.
629 : //!
630 : //! `a` is a null terminated instruction name from `???InstDB::nameData[]` table.
631 : //! `b` is a non-null terminated instruction name passed to `???Inst::getIdByName()`.
632 : static ASMJIT_INLINE int cmpInstName(const char* a, const char* b, size_t len) noexcept {
633 0 : for (size_t i = 0; i < len; i++) {
634 0 : int c = static_cast<int>(static_cast<uint8_t>(a[i])) -
635 0 : static_cast<int>(static_cast<uint8_t>(b[i])) ;
636 0 : if (c != 0) return c;
637 : }
638 :
639 0 : return static_cast<int>(a[len]);
640 : }
641 :
642 : // --------------------------------------------------------------------------
643 : // [BSwap]
644 : // --------------------------------------------------------------------------
645 :
646 : static ASMJIT_INLINE uint32_t byteswap32(uint32_t x) noexcept {
647 : #if ASMJIT_CC_MSC
648 : return static_cast<uint32_t>(_byteswap_ulong(x));
649 : #elif ASMJIT_CC_GCC_GE(4, 3, 0) || ASMJIT_CC_CLANG_GE(2, 6, 0)
650 : return __builtin_bswap32(x);
651 : #else
652 : uint32_t y = x & 0x00FFFF00U;
653 : x = (x << 24) + (x >> 24);
654 : y = (y << 8) + (y >> 8);
655 : return x + (y & 0x00FFFF00U);
656 : #endif
657 : }
658 :
659 : // --------------------------------------------------------------------------
660 : // [ReadMem]
661 : // --------------------------------------------------------------------------
662 :
663 : static ASMJIT_INLINE uint32_t readU8(const void* p) noexcept {
664 : return static_cast<uint32_t>(static_cast<const uint8_t*>(p)[0]);
665 : }
666 :
667 : static ASMJIT_INLINE int32_t readI8(const void* p) noexcept {
668 : return static_cast<int32_t>(static_cast<const int8_t*>(p)[0]);
669 : }
670 :
671 : template<unsigned int Alignment>
672 : static ASMJIT_INLINE uint32_t readU16xLE(const void* p) noexcept {
673 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
674 : if (ASMJIT_ARCH_LE && (ASMJIT_ARCH_UNALIGNED_16 || Alignment >= 2)) {
675 : return static_cast<uint32_t>(static_cast<const uint16_t*>(p)[0]);
676 : }
677 : else {
678 : uint32_t x = static_cast<uint32_t>(static_cast<const uint8_t*>(p)[0]);
679 : uint32_t y = static_cast<uint32_t>(static_cast<const uint8_t*>(p)[1]);
680 : return x + (y << 8);
681 : }
682 : }
683 :
684 : template<unsigned int Alignment>
685 : static ASMJIT_INLINE uint32_t readU16xBE(const void* p) noexcept {
686 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
687 : if (ASMJIT_ARCH_BE && (ASMJIT_ARCH_UNALIGNED_16 || Alignment >= 2)) {
688 : return static_cast<uint32_t>(static_cast<const uint16_t*>(p)[0]);
689 : }
690 : else {
691 : uint32_t x = static_cast<uint32_t>(static_cast<const uint8_t*>(p)[0]);
692 : uint32_t y = static_cast<uint32_t>(static_cast<const uint8_t*>(p)[1]);
693 : return (x << 8) + y;
694 : }
695 : }
696 :
697 : template<unsigned int Alignment>
698 : static ASMJIT_INLINE uint32_t readU16x(const void* p) noexcept {
699 : return ASMJIT_ARCH_LE ? readU16xLE<Alignment>(p) : readU16xBE<Alignment>(p);
700 : }
701 :
702 : template<unsigned int Alignment>
703 : static ASMJIT_INLINE int32_t readI16xLE(const void* p) noexcept {
704 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
705 : if (ASMJIT_ARCH_LE && (ASMJIT_ARCH_UNALIGNED_16 || Alignment >= 2)) {
706 : return static_cast<int32_t>(static_cast<const int16_t*>(p)[0]);
707 : }
708 : else {
709 : int32_t x = static_cast<int32_t>(static_cast<const uint8_t*>(p)[0]);
710 : int32_t y = static_cast<int32_t>(static_cast<const int8_t*>(p)[1]);
711 : return x + (y << 8);
712 : }
713 : }
714 :
715 : template<unsigned int Alignment>
716 : static ASMJIT_INLINE int32_t readI16xBE(const void* p) noexcept {
717 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
718 : if (ASMJIT_ARCH_BE && (ASMJIT_ARCH_UNALIGNED_16 || Alignment >= 2)) {
719 : return static_cast<int32_t>(static_cast<const int16_t*>(p)[0]);
720 : }
721 : else {
722 : int32_t x = static_cast<int32_t>(static_cast<const int8_t*>(p)[0]);
723 : int32_t y = static_cast<int32_t>(static_cast<const uint8_t*>(p)[1]);
724 : return (x << 8) + y;
725 : }
726 : }
727 :
728 : template<unsigned int Alignment>
729 : static ASMJIT_INLINE int32_t readI16x(const void* p) noexcept {
730 : return ASMJIT_ARCH_LE ? readI16xLE<Alignment>(p) : readI16xBE<Alignment>(p);
731 : }
732 :
733 : static ASMJIT_INLINE uint32_t readU16aLE(const void* p) noexcept { return readU16xLE<2>(p); }
734 : static ASMJIT_INLINE uint32_t readU16uLE(const void* p) noexcept { return readU16xLE<0>(p); }
735 :
736 : static ASMJIT_INLINE uint32_t readU16aBE(const void* p) noexcept { return readU16xBE<2>(p); }
737 : static ASMJIT_INLINE uint32_t readU16uBE(const void* p) noexcept { return readU16xBE<0>(p); }
738 :
739 : static ASMJIT_INLINE uint32_t readU16a(const void* p) noexcept { return readU16x<2>(p); }
740 : static ASMJIT_INLINE uint32_t readU16u(const void* p) noexcept { return readU16x<0>(p); }
741 :
742 : static ASMJIT_INLINE int32_t readI16aLE(const void* p) noexcept { return readI16xLE<2>(p); }
743 : static ASMJIT_INLINE int32_t readI16uLE(const void* p) noexcept { return readI16xLE<0>(p); }
744 :
745 : static ASMJIT_INLINE int32_t readI16aBE(const void* p) noexcept { return readI16xBE<2>(p); }
746 : static ASMJIT_INLINE int32_t readI16uBE(const void* p) noexcept { return readI16xBE<0>(p); }
747 :
748 : static ASMJIT_INLINE int32_t readI16a(const void* p) noexcept { return readI16x<2>(p); }
749 : static ASMJIT_INLINE int32_t readI16u(const void* p) noexcept { return readI16x<0>(p); }
750 :
751 : template<unsigned int Alignment>
752 : static ASMJIT_INLINE uint32_t readU32xLE(const void* p) noexcept {
753 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
754 : if (ASMJIT_ARCH_UNALIGNED_32 || Alignment >= 4) {
755 : uint32_t x = static_cast<const uint32_t*>(p)[0];
756 : return ASMJIT_ARCH_LE ? x : byteswap32(x);
757 : }
758 : else {
759 : uint32_t x = readU16xLE<Alignment>(static_cast<const uint8_t*>(p) + 0);
760 : uint32_t y = readU16xLE<Alignment>(static_cast<const uint8_t*>(p) + 2);
761 : return x + (y << 16);
762 : }
763 : }
764 :
765 : template<unsigned int Alignment>
766 : static ASMJIT_INLINE uint32_t readU32xBE(const void* p) noexcept {
767 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
768 : if (ASMJIT_ARCH_UNALIGNED_32 || Alignment >= 4) {
769 : uint32_t x = static_cast<const uint32_t*>(p)[0];
770 : return ASMJIT_ARCH_BE ? x : byteswap32(x);
771 : }
772 : else {
773 : uint32_t x = readU16xBE<Alignment>(static_cast<const uint8_t*>(p) + 0);
774 : uint32_t y = readU16xBE<Alignment>(static_cast<const uint8_t*>(p) + 2);
775 : return (x << 16) + y;
776 : }
777 : }
778 :
779 : template<unsigned int Alignment>
780 : static ASMJIT_INLINE uint32_t readU32x(const void* p) noexcept {
781 : return ASMJIT_ARCH_LE ? readU32xLE<Alignment>(p) : readU32xBE<Alignment>(p);
782 : }
783 :
784 : template<unsigned int Alignment>
785 : static ASMJIT_INLINE int32_t readI32xLE(const void* p) noexcept {
786 : return static_cast<int32_t>(readU32xLE<Alignment>(p));
787 : }
788 :
789 : template<unsigned int Alignment>
790 : static ASMJIT_INLINE int32_t readI32xBE(const void* p) noexcept {
791 : return static_cast<int32_t>(readU32xBE<Alignment>(p));
792 : }
793 :
794 : template<unsigned int Alignment>
795 : static ASMJIT_INLINE int32_t readI32x(const void* p) noexcept {
796 : return ASMJIT_ARCH_LE ? readI32xLE<Alignment>(p) : readI32xBE<Alignment>(p);
797 : }
798 :
799 : static ASMJIT_INLINE uint32_t readU32a(const void* p) noexcept { return readU32x<4>(p); }
800 : static ASMJIT_INLINE uint32_t readU32u(const void* p) noexcept { return readU32x<0>(p); }
801 :
802 : static ASMJIT_INLINE uint32_t readU32aLE(const void* p) noexcept { return readU32xLE<4>(p); }
803 : static ASMJIT_INLINE uint32_t readU32uLE(const void* p) noexcept { return readU32xLE<0>(p); }
804 :
805 : static ASMJIT_INLINE uint32_t readU32aBE(const void* p) noexcept { return readU32xBE<4>(p); }
806 : static ASMJIT_INLINE uint32_t readU32uBE(const void* p) noexcept { return readU32xBE<0>(p); }
807 :
808 : static ASMJIT_INLINE int32_t readI32a(const void* p) noexcept { return readI32x<4>(p); }
809 : static ASMJIT_INLINE int32_t readI32u(const void* p) noexcept { return readI32x<0>(p); }
810 :
811 : static ASMJIT_INLINE int32_t readI32aLE(const void* p) noexcept { return readI32xLE<4>(p); }
812 : static ASMJIT_INLINE int32_t readI32uLE(const void* p) noexcept { return readI32xLE<0>(p); }
813 :
814 : static ASMJIT_INLINE int32_t readI32aBE(const void* p) noexcept { return readI32xBE<4>(p); }
815 : static ASMJIT_INLINE int32_t readI32uBE(const void* p) noexcept { return readI32xBE<0>(p); }
816 :
817 : template<unsigned int Alignment>
818 : static ASMJIT_INLINE uint64_t readU64xLE(const void* p) noexcept {
819 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
820 : if (ASMJIT_ARCH_LE && (ASMJIT_ARCH_UNALIGNED_64 || Alignment >= 8)) {
821 : return static_cast<const uint64_t*>(p)[0];
822 : }
823 : else {
824 : uint32_t x = readU32xLE<Alignment / 2U>(static_cast<const uint8_t*>(p) + 0);
825 : uint32_t y = readU32xLE<Alignment / 2U>(static_cast<const uint8_t*>(p) + 4);
826 : return static_cast<uint64_t>(x) + (static_cast<uint64_t>(y) << 32);
827 : }
828 : }
829 :
830 : template<unsigned int Alignment>
831 : static ASMJIT_INLINE uint64_t readU64xBE(const void* p) noexcept {
832 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
833 : if (ASMJIT_ARCH_BE && (ASMJIT_ARCH_UNALIGNED_64 || Alignment >= 8)) {
834 : return static_cast<const uint64_t*>(p)[0];
835 : }
836 : else {
837 : uint32_t x = readU32xLE<Alignment / 2U>(static_cast<const uint8_t*>(p) + 0);
838 : uint32_t y = readU32xLE<Alignment / 2U>(static_cast<const uint8_t*>(p) + 4);
839 : return (static_cast<uint64_t>(x) << 32) + static_cast<uint64_t>(y);
840 : }
841 : }
842 :
843 : template<unsigned int Alignment>
844 : static ASMJIT_INLINE uint64_t readU64x(const void* p) noexcept {
845 : return ASMJIT_ARCH_LE ? readU64xLE<Alignment>(p) : readU64xBE<Alignment>(p);
846 : }
847 :
848 : template<unsigned int Alignment>
849 : static ASMJIT_INLINE int64_t readI64xLE(const void* p) noexcept {
850 : return static_cast<int64_t>(readU64xLE<Alignment>(p));
851 : }
852 :
853 : template<unsigned int Alignment>
854 : static ASMJIT_INLINE int64_t readI64xBE(const void* p) noexcept {
855 : return static_cast<int64_t>(readU64xBE<Alignment>(p));
856 : }
857 :
858 : template<unsigned int Alignment>
859 : static ASMJIT_INLINE int64_t readI64x(const void* p) noexcept {
860 : return ASMJIT_ARCH_LE ? readI64xLE<Alignment>(p) : readI64xBE<Alignment>(p);
861 : }
862 :
863 : static ASMJIT_INLINE uint64_t readU64a(const void* p) noexcept { return readU64x<8>(p); }
864 : static ASMJIT_INLINE uint64_t readU64u(const void* p) noexcept { return readU64x<0>(p); }
865 :
866 : static ASMJIT_INLINE uint64_t readU64aLE(const void* p) noexcept { return readU64xLE<8>(p); }
867 : static ASMJIT_INLINE uint64_t readU64uLE(const void* p) noexcept { return readU64xLE<0>(p); }
868 :
869 : static ASMJIT_INLINE uint64_t readU64aBE(const void* p) noexcept { return readU64xBE<8>(p); }
870 : static ASMJIT_INLINE uint64_t readU64uBE(const void* p) noexcept { return readU64xBE<0>(p); }
871 :
872 : static ASMJIT_INLINE int64_t readI64a(const void* p) noexcept { return readI64x<8>(p); }
873 : static ASMJIT_INLINE int64_t readI64u(const void* p) noexcept { return readI64x<0>(p); }
874 :
875 : static ASMJIT_INLINE int64_t readI64aLE(const void* p) noexcept { return readI64xLE<8>(p); }
876 : static ASMJIT_INLINE int64_t readI64uLE(const void* p) noexcept { return readI64xLE<0>(p); }
877 :
878 : static ASMJIT_INLINE int64_t readI64aBE(const void* p) noexcept { return readI64xBE<8>(p); }
879 : static ASMJIT_INLINE int64_t readI64uBE(const void* p) noexcept { return readI64xBE<0>(p); }
880 :
881 : // --------------------------------------------------------------------------
882 : // [WriteMem]
883 : // --------------------------------------------------------------------------
884 :
885 : static ASMJIT_INLINE void writeU8(void* p, uint32_t x) noexcept {
886 0 : static_cast<uint8_t*>(p)[0] = static_cast<uint8_t>(x & 0xFFU);
887 0 : }
888 :
889 : static ASMJIT_INLINE void writeI8(void* p, int32_t x) noexcept {
890 : static_cast<uint8_t*>(p)[0] = static_cast<uint8_t>(x & 0xFF);
891 : }
892 :
893 : template<unsigned int Alignment>
894 : static ASMJIT_INLINE void writeU16xLE(void* p, uint32_t x) noexcept {
895 0 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
896 : if (ASMJIT_ARCH_LE && (ASMJIT_ARCH_UNALIGNED_16 || Alignment >= 2)) {
897 0 : static_cast<uint16_t*>(p)[0] = static_cast<uint16_t>(x & 0xFFFFU);
898 : }
899 : else {
900 : static_cast<uint8_t*>(p)[0] = static_cast<uint8_t>((x ) & 0xFFU);
901 : static_cast<uint8_t*>(p)[1] = static_cast<uint8_t>((x >> 8) & 0xFFU);
902 : }
903 : }
904 :
905 : template<unsigned int Alignment>
906 : static ASMJIT_INLINE void writeU16xBE(void* p, uint32_t x) noexcept {
907 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
908 : if (ASMJIT_ARCH_BE && (ASMJIT_ARCH_UNALIGNED_16 || Alignment >= 2)) {
909 : static_cast<uint16_t*>(p)[0] = static_cast<uint16_t>(x & 0xFFFFU);
910 : }
911 : else {
912 : static_cast<uint8_t*>(p)[0] = static_cast<uint8_t>((x >> 8) & 0xFFU);
913 : static_cast<uint8_t*>(p)[1] = static_cast<uint8_t>((x ) & 0xFFU);
914 : }
915 : }
916 :
917 : template<unsigned int Alignment>
918 : static ASMJIT_INLINE void writeU16x(void* p, uint32_t x) noexcept {
919 : if (ASMJIT_ARCH_LE)
920 : writeU16xLE<Alignment>(p, x);
921 : else
922 : writeU16xBE<Alignment>(p, x);
923 : }
924 :
925 : template<unsigned int Alignment>
926 : static ASMJIT_INLINE void writeI16xLE(void* p, int32_t x) noexcept {
927 : writeU16xLE<Alignment>(p, static_cast<uint32_t>(x));
928 : }
929 :
930 : template<unsigned int Alignment>
931 : static ASMJIT_INLINE void writeI16xBE(void* p, int32_t x) noexcept {
932 : writeU16xBE<Alignment>(p, static_cast<uint32_t>(x));
933 : }
934 :
935 : template<unsigned int Alignment>
936 : static ASMJIT_INLINE void writeI16x(void* p, int32_t x) noexcept {
937 : writeU16x<Alignment>(p, static_cast<uint32_t>(x));
938 : }
939 :
940 : static ASMJIT_INLINE void writeU16aLE(void* p, uint32_t x) noexcept { writeU16xLE<2>(p, x); }
941 : static ASMJIT_INLINE void writeU16uLE(void* p, uint32_t x) noexcept { writeU16xLE<0>(p, x); }
942 :
943 : static ASMJIT_INLINE void writeU16aBE(void* p, uint32_t x) noexcept { writeU16xBE<2>(p, x); }
944 : static ASMJIT_INLINE void writeU16uBE(void* p, uint32_t x) noexcept { writeU16xBE<0>(p, x); }
945 :
946 : static ASMJIT_INLINE void writeU16a(void* p, uint32_t x) noexcept { writeU16x<2>(p, x); }
947 : static ASMJIT_INLINE void writeU16u(void* p, uint32_t x) noexcept { writeU16x<0>(p, x); }
948 :
949 : static ASMJIT_INLINE void writeI16aLE(void* p, int32_t x) noexcept { writeI16xLE<2>(p, x); }
950 : static ASMJIT_INLINE void writeI16uLE(void* p, int32_t x) noexcept { writeI16xLE<0>(p, x); }
951 :
952 : static ASMJIT_INLINE void writeI16aBE(void* p, int32_t x) noexcept { writeI16xBE<2>(p, x); }
953 : static ASMJIT_INLINE void writeI16uBE(void* p, int32_t x) noexcept { writeI16xBE<0>(p, x); }
954 :
955 : static ASMJIT_INLINE void writeI16a(void* p, int32_t x) noexcept { writeI16x<2>(p, x); }
956 : static ASMJIT_INLINE void writeI16u(void* p, int32_t x) noexcept { writeI16x<0>(p, x); }
957 :
958 : template<unsigned int Alignment>
959 : static ASMJIT_INLINE void writeU32xLE(void* p, uint32_t x) noexcept {
960 159534 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
961 : if (ASMJIT_ARCH_UNALIGNED_32 || Alignment >= 4) {
962 159534 : static_cast<uint32_t*>(p)[0] = ASMJIT_ARCH_LE ? x : byteswap32(x);
963 : }
964 : else {
965 : writeU16xLE<Alignment>(static_cast<uint8_t*>(p) + 0, x >> 16);
966 : writeU16xLE<Alignment>(static_cast<uint8_t*>(p) + 2, x);
967 : }
968 : }
969 :
970 : template<unsigned int Alignment>
971 : static ASMJIT_INLINE void writeU32xBE(void* p, uint32_t x) noexcept {
972 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
973 : if (ASMJIT_ARCH_UNALIGNED_32 || Alignment >= 4) {
974 : static_cast<uint32_t*>(p)[0] = ASMJIT_ARCH_BE ? x : byteswap32(x);
975 : }
976 : else {
977 : writeU16xBE<Alignment>(static_cast<uint8_t*>(p) + 0, x);
978 : writeU16xBE<Alignment>(static_cast<uint8_t*>(p) + 2, x >> 16);
979 : }
980 : }
981 :
982 : template<unsigned int Alignment>
983 : static ASMJIT_INLINE void writeU32x(void* p, uint32_t x) noexcept {
984 : if (ASMJIT_ARCH_LE)
985 : writeU32xLE<Alignment>(p, x);
986 : else
987 : writeU32xBE<Alignment>(p, x);
988 : }
989 :
990 : template<unsigned int Alignment>
991 : static ASMJIT_INLINE void writeI32xLE(void* p, int32_t x) noexcept {
992 : writeU32xLE<Alignment>(p, static_cast<uint32_t>(x));
993 : }
994 :
995 : template<unsigned int Alignment>
996 : static ASMJIT_INLINE void writeI32xBE(void* p, int32_t x) noexcept {
997 : writeU32xBE<Alignment>(p, static_cast<uint32_t>(x));
998 : }
999 :
1000 : template<unsigned int Alignment>
1001 : static ASMJIT_INLINE void writeI32x(void* p, int32_t x) noexcept {
1002 : writeU32x<Alignment>(p, static_cast<uint32_t>(x));
1003 : }
1004 :
1005 : static ASMJIT_INLINE void writeU32aLE(void* p, uint32_t x) noexcept { writeU32xLE<4>(p, x); }
1006 : static ASMJIT_INLINE void writeU32uLE(void* p, uint32_t x) noexcept { writeU32xLE<0>(p, x); }
1007 :
1008 : static ASMJIT_INLINE void writeU32aBE(void* p, uint32_t x) noexcept { writeU32xBE<4>(p, x); }
1009 : static ASMJIT_INLINE void writeU32uBE(void* p, uint32_t x) noexcept { writeU32xBE<0>(p, x); }
1010 :
1011 : static ASMJIT_INLINE void writeU32a(void* p, uint32_t x) noexcept { writeU32x<4>(p, x); }
1012 0 : static ASMJIT_INLINE void writeU32u(void* p, uint32_t x) noexcept { writeU32x<0>(p, x); }
1013 :
1014 : static ASMJIT_INLINE void writeI32aLE(void* p, int32_t x) noexcept { writeI32xLE<4>(p, x); }
1015 : static ASMJIT_INLINE void writeI32uLE(void* p, int32_t x) noexcept { writeI32xLE<0>(p, x); }
1016 :
1017 : static ASMJIT_INLINE void writeI32aBE(void* p, int32_t x) noexcept { writeI32xBE<4>(p, x); }
1018 : static ASMJIT_INLINE void writeI32uBE(void* p, int32_t x) noexcept { writeI32xBE<0>(p, x); }
1019 :
1020 : static ASMJIT_INLINE void writeI32a(void* p, int32_t x) noexcept { writeI32x<4>(p, x); }
1021 0 : static ASMJIT_INLINE void writeI32u(void* p, int32_t x) noexcept { writeI32x<0>(p, x); }
1022 :
1023 : template<unsigned int Alignment>
1024 : static ASMJIT_INLINE void writeU64xLE(void* p, uint64_t x) noexcept {
1025 0 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
1026 : if (ASMJIT_ARCH_LE && (ASMJIT_ARCH_UNALIGNED_64 || Alignment >= 8)) {
1027 0 : static_cast<uint64_t*>(p)[0] = x;
1028 : }
1029 : else {
1030 : writeU32xLE<Alignment / 2U>(static_cast<uint8_t*>(p) + 0, static_cast<uint32_t>(x >> 32));
1031 : writeU32xLE<Alignment / 2U>(static_cast<uint8_t*>(p) + 4, static_cast<uint32_t>(x & 0xFFFFFFFFU));
1032 : }
1033 : }
1034 :
1035 : template<unsigned int Alignment>
1036 : static ASMJIT_INLINE void writeU64xBE(void* p, uint64_t x) noexcept {
1037 : ASMJIT_ASSUME_ALIGNED(p, Alignment > 1 ? Alignment : 1U);
1038 : if (ASMJIT_ARCH_BE && (ASMJIT_ARCH_UNALIGNED_64 || Alignment >= 8)) {
1039 : static_cast<uint64_t*>(p)[0] = x;
1040 : }
1041 : else {
1042 : writeU32xBE<Alignment / 2U>(static_cast<uint8_t*>(p) + 0, static_cast<uint32_t>(x & 0xFFFFFFFFU));
1043 : writeU32xBE<Alignment / 2U>(static_cast<uint8_t*>(p) + 4, static_cast<uint32_t>(x >> 32));
1044 : }
1045 : }
1046 :
1047 : template<unsigned int Alignment>
1048 : static ASMJIT_INLINE void writeU64x(void* p, uint64_t x) noexcept {
1049 : if (ASMJIT_ARCH_LE)
1050 : writeU64xLE<Alignment>(p, x);
1051 : else
1052 : writeU64xBE<Alignment>(p, x);
1053 : }
1054 :
1055 : template<unsigned int Alignment>
1056 : static ASMJIT_INLINE void writeI64xLE(void* p, int64_t x) noexcept {
1057 : writeU64xLE<Alignment>(p, static_cast<uint64_t>(x));
1058 : }
1059 :
1060 : template<unsigned int Alignment>
1061 : static ASMJIT_INLINE void writeI64xBE(void* p, int64_t x) noexcept {
1062 : writeU64xBE<Alignment>(p, static_cast<uint64_t>(x));
1063 : }
1064 :
1065 : template<unsigned int Alignment>
1066 : static ASMJIT_INLINE void writeI64x(void* p, int64_t x) noexcept {
1067 : writeU64x<Alignment>(p, static_cast<uint64_t>(x));
1068 : }
1069 :
1070 : static ASMJIT_INLINE void writeU64aLE(void* p, uint64_t x) noexcept { writeU64xLE<8>(p, x); }
1071 : static ASMJIT_INLINE void writeU64uLE(void* p, uint64_t x) noexcept { writeU64xLE<0>(p, x); }
1072 :
1073 : static ASMJIT_INLINE void writeU64aBE(void* p, uint64_t x) noexcept { writeU64xBE<8>(p, x); }
1074 : static ASMJIT_INLINE void writeU64uBE(void* p, uint64_t x) noexcept { writeU64xBE<0>(p, x); }
1075 :
1076 : static ASMJIT_INLINE void writeU64a(void* p, uint64_t x) noexcept { writeU64x<8>(p, x); }
1077 0 : static ASMJIT_INLINE void writeU64u(void* p, uint64_t x) noexcept { writeU64x<0>(p, x); }
1078 :
1079 : static ASMJIT_INLINE void writeI64aLE(void* p, int64_t x) noexcept { writeI64xLE<8>(p, x); }
1080 : static ASMJIT_INLINE void writeI64uLE(void* p, int64_t x) noexcept { writeI64xLE<0>(p, x); }
1081 :
1082 : static ASMJIT_INLINE void writeI64aBE(void* p, int64_t x) noexcept { writeI64xBE<8>(p, x); }
1083 : static ASMJIT_INLINE void writeI64uBE(void* p, int64_t x) noexcept { writeI64xBE<0>(p, x); }
1084 :
1085 : static ASMJIT_INLINE void writeI64a(void* p, int64_t x) noexcept { writeI64x<8>(p, x); }
1086 : static ASMJIT_INLINE void writeI64u(void* p, int64_t x) noexcept { writeI64x<0>(p, x); }
1087 : } // Utils namespace
1088 :
1089 : // ============================================================================
1090 : // [asmjit::UInt64]
1091 : // ============================================================================
1092 :
1093 : union UInt64 {
1094 : // --------------------------------------------------------------------------
1095 : // [Construction / Destruction]
1096 : // --------------------------------------------------------------------------
1097 :
1098 : ASMJIT_INLINE UInt64 fromUInt64(uint64_t val) noexcept {
1099 : UInt64 data;
1100 : data.setUInt64(val);
1101 : return data;
1102 : }
1103 :
1104 : ASMJIT_INLINE UInt64 fromUInt64(const UInt64& val) noexcept {
1105 : UInt64 data;
1106 : data.setUInt64(val);
1107 : return data;
1108 : }
1109 :
1110 : // --------------------------------------------------------------------------
1111 : // [Reset]
1112 : // --------------------------------------------------------------------------
1113 :
1114 : ASMJIT_INLINE void reset() noexcept {
1115 : if (ASMJIT_ARCH_64BIT) {
1116 1097309 : u64 = 0;
1117 : }
1118 : else {
1119 : u32[0] = 0;
1120 : u32[1] = 0;
1121 : }
1122 : }
1123 :
1124 : // --------------------------------------------------------------------------
1125 : // [Accessors]
1126 : // --------------------------------------------------------------------------
1127 :
1128 : ASMJIT_INLINE uint64_t getUInt64() const noexcept {
1129 : return u64;
1130 : }
1131 :
1132 : ASMJIT_INLINE UInt64& setUInt64(uint64_t val) noexcept {
1133 : u64 = val;
1134 : return *this;
1135 : }
1136 :
1137 : ASMJIT_INLINE UInt64& setUInt64(const UInt64& val) noexcept {
1138 : if (ASMJIT_ARCH_64BIT) {
1139 : u64 = val.u64;
1140 : }
1141 : else {
1142 : u32[0] = val.u32[0];
1143 : u32[1] = val.u32[1];
1144 : }
1145 : return *this;
1146 : }
1147 :
1148 : ASMJIT_INLINE UInt64& setPacked_2x32(uint32_t u0, uint32_t u1) noexcept {
1149 : if (ASMJIT_ARCH_64BIT) {
1150 967609 : u64 = Utils::pack64_2x32(u0, u1);
1151 : }
1152 : else {
1153 : u32[0] = u0;
1154 : u32[1] = u1;
1155 : }
1156 : return *this;
1157 : }
1158 :
1159 : // --------------------------------------------------------------------------
1160 : // [Add]
1161 : // --------------------------------------------------------------------------
1162 :
1163 : ASMJIT_INLINE UInt64& add(uint64_t val) noexcept {
1164 : u64 += val;
1165 : return *this;
1166 : }
1167 :
1168 : ASMJIT_INLINE UInt64& add(const UInt64& val) noexcept {
1169 : if (ASMJIT_ARCH_64BIT) {
1170 : u64 += val.u64;
1171 : }
1172 : else {
1173 : u32[0] += val.u32[0];
1174 : u32[1] += val.u32[1];
1175 : }
1176 : return *this;
1177 : }
1178 :
1179 : // --------------------------------------------------------------------------
1180 : // [Sub]
1181 : // --------------------------------------------------------------------------
1182 :
1183 : ASMJIT_INLINE UInt64& sub(uint64_t val) noexcept {
1184 : u64 -= val;
1185 : return *this;
1186 : }
1187 :
1188 : ASMJIT_INLINE UInt64& sub(const UInt64& val) noexcept {
1189 : if (ASMJIT_ARCH_64BIT) {
1190 : u64 -= val.u64;
1191 : }
1192 : else {
1193 : u32[0] -= val.u32[0];
1194 : u32[1] -= val.u32[1];
1195 : }
1196 : return *this;
1197 : }
1198 :
1199 : // --------------------------------------------------------------------------
1200 : // [And]
1201 : // --------------------------------------------------------------------------
1202 :
1203 : ASMJIT_INLINE UInt64& and_(uint64_t val) noexcept {
1204 : u64 &= val;
1205 : return *this;
1206 : }
1207 :
1208 : ASMJIT_INLINE UInt64& and_(const UInt64& val) noexcept {
1209 : if (ASMJIT_ARCH_64BIT) {
1210 : u64 &= val.u64;
1211 : }
1212 : else {
1213 : u32[0] &= val.u32[0];
1214 : u32[1] &= val.u32[1];
1215 : }
1216 : return *this;
1217 : }
1218 :
1219 : // --------------------------------------------------------------------------
1220 : // [AndNot]
1221 : // --------------------------------------------------------------------------
1222 :
1223 : ASMJIT_INLINE UInt64& andNot(uint64_t val) noexcept {
1224 : u64 &= ~val;
1225 : return *this;
1226 : }
1227 :
1228 : ASMJIT_INLINE UInt64& andNot(const UInt64& val) noexcept {
1229 : if (ASMJIT_ARCH_64BIT) {
1230 : u64 &= ~val.u64;
1231 : }
1232 : else {
1233 : u32[0] &= ~val.u32[0];
1234 : u32[1] &= ~val.u32[1];
1235 : }
1236 : return *this;
1237 : }
1238 :
1239 : // --------------------------------------------------------------------------
1240 : // [Or]
1241 : // --------------------------------------------------------------------------
1242 :
1243 : ASMJIT_INLINE UInt64& or_(uint64_t val) noexcept {
1244 : u64 |= val;
1245 : return *this;
1246 : }
1247 :
1248 : ASMJIT_INLINE UInt64& or_(const UInt64& val) noexcept {
1249 : if (ASMJIT_ARCH_64BIT) {
1250 929499 : u64 |= val.u64;
1251 : }
1252 : else {
1253 : u32[0] |= val.u32[0];
1254 : u32[1] |= val.u32[1];
1255 : }
1256 : return *this;
1257 : }
1258 :
1259 : // --------------------------------------------------------------------------
1260 : // [Xor]
1261 : // --------------------------------------------------------------------------
1262 :
1263 : ASMJIT_INLINE UInt64& xor_(uint64_t val) noexcept {
1264 : u64 ^= val;
1265 : return *this;
1266 : }
1267 :
1268 : ASMJIT_INLINE UInt64& xor_(const UInt64& val) noexcept {
1269 : if (ASMJIT_ARCH_64BIT) {
1270 : u64 ^= val.u64;
1271 : }
1272 : else {
1273 : u32[0] ^= val.u32[0];
1274 : u32[1] ^= val.u32[1];
1275 : }
1276 : return *this;
1277 : }
1278 :
1279 : // --------------------------------------------------------------------------
1280 : // [Eq]
1281 : // --------------------------------------------------------------------------
1282 :
1283 : ASMJIT_INLINE bool isZero() const noexcept {
1284 : if (ASMJIT_ARCH_64BIT)
1285 : return u64 == 0;
1286 : else
1287 : return (u32[0] | u32[1]) == 0;
1288 : }
1289 :
1290 : ASMJIT_INLINE bool isNonZero() const noexcept {
1291 : if (ASMJIT_ARCH_64BIT)
1292 : return u64 != 0;
1293 : else
1294 : return (u32[0] | u32[1]) != 0;
1295 : }
1296 :
1297 : ASMJIT_INLINE bool eq(uint64_t val) const noexcept {
1298 : return u64 == val;
1299 : }
1300 :
1301 : ASMJIT_INLINE bool eq(const UInt64& val) const noexcept {
1302 : if (ASMJIT_ARCH_64BIT)
1303 : return u64 == val.u64;
1304 : else
1305 : return u32[0] == val.u32[0] && u32[1] == val.u32[1];
1306 : }
1307 :
1308 : // --------------------------------------------------------------------------
1309 : // [Operator Overload]
1310 : // --------------------------------------------------------------------------
1311 :
1312 : ASMJIT_INLINE UInt64& operator+=(uint64_t val) noexcept { return add(val); }
1313 : ASMJIT_INLINE UInt64& operator+=(const UInt64& val) noexcept { return add(val); }
1314 :
1315 : ASMJIT_INLINE UInt64& operator-=(uint64_t val) noexcept { return sub(val); }
1316 : ASMJIT_INLINE UInt64& operator-=(const UInt64& val) noexcept { return sub(val); }
1317 :
1318 : ASMJIT_INLINE UInt64& operator&=(uint64_t val) noexcept { return and_(val); }
1319 : ASMJIT_INLINE UInt64& operator&=(const UInt64& val) noexcept { return and_(val); }
1320 :
1321 : ASMJIT_INLINE UInt64& operator|=(uint64_t val) noexcept { return or_(val); }
1322 : ASMJIT_INLINE UInt64& operator|=(const UInt64& val) noexcept { return or_(val); }
1323 :
1324 : ASMJIT_INLINE UInt64& operator^=(uint64_t val) noexcept { return xor_(val); }
1325 : ASMJIT_INLINE UInt64& operator^=(const UInt64& val) noexcept { return xor_(val); }
1326 :
1327 : ASMJIT_INLINE bool operator==(uint64_t val) const noexcept { return eq(val); }
1328 : ASMJIT_INLINE bool operator==(const UInt64& val) const noexcept { return eq(val); }
1329 :
1330 : ASMJIT_INLINE bool operator!=(uint64_t val) const noexcept { return !eq(val); }
1331 : ASMJIT_INLINE bool operator!=(const UInt64& val) const noexcept { return !eq(val); }
1332 :
1333 : ASMJIT_INLINE bool operator<(uint64_t val) const noexcept { return u64 < val; }
1334 : ASMJIT_INLINE bool operator<(const UInt64& val) const noexcept { return u64 < val.u64; }
1335 :
1336 : ASMJIT_INLINE bool operator<=(uint64_t val) const noexcept { return u64 <= val; }
1337 : ASMJIT_INLINE bool operator<=(const UInt64& val) const noexcept { return u64 <= val.u64; }
1338 :
1339 : ASMJIT_INLINE bool operator>(uint64_t val) const noexcept { return u64 > val; }
1340 : ASMJIT_INLINE bool operator>(const UInt64& val) const noexcept { return u64 > val.u64; }
1341 :
1342 : ASMJIT_INLINE bool operator>=(uint64_t val) const noexcept { return u64 >= val; }
1343 : ASMJIT_INLINE bool operator>=(const UInt64& val) const noexcept { return u64 >= val.u64; }
1344 :
1345 : // --------------------------------------------------------------------------
1346 : // [Members]
1347 : // --------------------------------------------------------------------------
1348 :
1349 : int8_t i8[8]; //!< 8-bit signed integer (8x).
1350 : uint8_t u8[8]; //!< 8-bit unsigned integer (8x).
1351 :
1352 : int16_t i16[4]; //!< 16-bit signed integer (4x).
1353 : uint16_t u16[4]; //!< 16-bit unsigned integer (4x).
1354 :
1355 : int32_t i32[2]; //!< 32-bit signed integer (2x).
1356 : uint32_t u32[2]; //!< 32-bit unsigned integer (2x).
1357 :
1358 : int64_t i64; //!< 64-bit signed integer.
1359 : uint64_t u64; //!< 64-bit unsigned integer.
1360 :
1361 : float f32[2]; //!< 32-bit floating point (2x).
1362 : double f64; //!< 64-bit floating point.
1363 :
1364 : #if ASMJIT_ARCH_LE
1365 : struct { float f32Lo, f32Hi; };
1366 : struct { int32_t i32Lo, i32Hi; };
1367 : struct { uint32_t u32Lo, u32Hi; };
1368 : #else
1369 : struct { float f32Hi, f32Lo; };
1370 : struct { int32_t i32Hi, i32Lo; };
1371 : struct { uint32_t u32Hi, u32Lo; };
1372 : #endif // ASMJIT_ARCH_LE
1373 : };
1374 :
1375 : //! \}
1376 :
1377 : } // asmjit namespace
1378 : } // namespace PLMD
1379 :
1380 : // [Api-End]
1381 : #include "./asmjit_apiend.h"
1382 :
1383 : // [Guard]
1384 : #endif // _ASMJIT_BASE_UTILS_H
1385 : #pragma GCC diagnostic pop
1386 : #endif // __PLUMED_HAS_ASMJIT
1387 : #endif
|