Line data Source code
1 : #ifdef __PLUMED_HAS_ASMJIT
2 : // This file is part of AsmJit project <https://asmjit.com>
3 : //
4 : // See asmjit.h or LICENSE.md for license and copyright information
5 : // SPDX-License-Identifier: Zlib
6 :
7 : #ifndef ASMJIT_CORE_OPERAND_H_INCLUDED
8 : #define ASMJIT_CORE_OPERAND_H_INCLUDED
9 :
10 : #include "archcommons.h"
11 : #include "support.h"
12 : #include "type.h"
13 :
14 : ASMJIT_BEGIN_NAMESPACE
15 :
16 : //! \addtogroup asmjit_assembler
17 : //! \{
18 :
19 : //! Operand type used by \ref Operand_.
20 : enum class OperandType : uint32_t {
21 : //! Not an operand or not initialized.
22 : kNone = 0,
23 : //! Operand is a register.
24 : kReg = 1,
25 : //! Operand is a memory.
26 : kMem = 2,
27 : //! Operand is an immediate value.
28 : kImm = 3,
29 : //! Operand is a label.
30 : kLabel = 4,
31 :
32 : //! Maximum value of `OperandType`.
33 : kMaxValue = kLabel
34 : };
35 :
36 : static_assert(uint32_t(OperandType::kMem) == uint32_t(OperandType::kReg) + 1,
37 : "AsmJit requires that `OperandType::kMem` equals to `OperandType::kReg + 1`");
38 :
39 : //! Register mask is a convenience typedef that describes a mask where each bit describes a physical register id
40 : //! in the same \ref RegGroup. At the moment 32 bits are enough as AsmJit doesn't support any architecture that
41 : //! would provide more than 32 registers for a register group.
42 : typedef uint32_t RegMask;
43 :
44 : //! Register type.
45 : //!
46 : //! Provides a unique type that can be used to identify a register or its view.
47 : enum class RegType : uint8_t {
48 : //! No register - unused, invalid, multiple meanings.
49 : kNone = 0,
50 :
51 : //! This is not a register type. This value is reserved for a \ref Label that used in \ref BaseMem as a base.
52 : //!
53 : //! Label tag is used as a sub-type, forming a unique signature across all operand types as 0x1 is never associated
54 : //! with any register type. This means that a memory operand's BASE register can be constructed from virtually any
55 : //! operand (register vs. label) by just assigning its type (register type or label-tag) and operand id.
56 : kLabelTag = 1,
57 :
58 : //! Universal type describing program counter (PC) or instruction pointer (IP) register, if the target architecture
59 : //! actually exposes it as a separate register type, which most modern targets do.
60 : kPC = 2,
61 :
62 : //! 8-bit low general purpose register (X86).
63 : kGp8Lo = 3,
64 : //! 8-bit high general purpose register (X86).
65 : kGp8Hi = 4,
66 : //! 16-bit general purpose register (X86).
67 : kGp16 = 5,
68 : //! 32-bit general purpose register (X86|ARM).
69 : kGp32 = 6,
70 : //! 64-bit general purpose register (X86|ARM).
71 : kGp64 = 7,
72 : //! 8-bit view of a vector register (ARM).
73 : kVec8 = 8,
74 : //! 16-bit view of a vector register (ARM).
75 : kVec16 = 9,
76 : //! 32-bit view of a vector register (ARM).
77 : kVec32 = 10,
78 : //! 64-bit view of a vector register (ARM).
79 : //!
80 : //! \note This is never used for MMX registers on X86, MMX registers have its own category.
81 : kVec64 = 11,
82 : //! 128-bit view of a vector register (X86|ARM).
83 : kVec128 = 12,
84 : //! 256-bit view of a vector register (X86).
85 : kVec256 = 13,
86 : //! 512-bit view of a vector register (X86).
87 : kVec512 = 14,
88 : //! 1024-bit view of a vector register (future).
89 : kVec1024 = 15,
90 : //! View of a vector register, which width is implementation specific (AArch64).
91 : kVecNLen = 16,
92 :
93 : //! Mask register (X86).
94 : kMask = 17,
95 :
96 : //! Start of architecture dependent register types.
97 : kExtra = 18,
98 :
99 : // X86 Specific Register Types
100 : // ---------------------------
101 :
102 : // X86 Specific Register Types
103 : // ===========================
104 :
105 : //! Instruction pointer (RIP), only addressable in \ref x86::Mem in 64-bit targets.
106 : kX86_Rip = kPC,
107 : //! Low GPB register (AL, BL, CL, DL, ...).
108 : kX86_GpbLo = kGp8Lo,
109 : //! High GPB register (AH, BH, CH, DH only).
110 : kX86_GpbHi = kGp8Hi,
111 : //! GPW register.
112 : kX86_Gpw = kGp16,
113 : //! GPD register.
114 : kX86_Gpd = kGp32,
115 : //! GPQ register (64-bit).
116 : kX86_Gpq = kGp64,
117 : //! XMM register (SSE+).
118 : kX86_Xmm = kVec128,
119 : //! YMM register (AVX+).
120 : kX86_Ymm = kVec256,
121 : //! ZMM register (AVX512+).
122 : kX86_Zmm = kVec512,
123 : //! K register (AVX512+).
124 : kX86_KReg = kMask,
125 : //! MMX register.
126 : kX86_Mm = kExtra + 0,
127 : //! Segment register (None, ES, CS, SS, DS, FS, GS).
128 : kX86_SReg = kExtra + 1,
129 : //! Control register (CR).
130 : kX86_CReg = kExtra + 2,
131 : //! Debug register (DR).
132 : kX86_DReg = kExtra + 3,
133 : //! FPU (x87) register.
134 : kX86_St = kExtra + 4,
135 : //! Bound register (BND).
136 : kX86_Bnd = kExtra + 5,
137 : //! TMM register (AMX_TILE)
138 : kX86_Tmm = kExtra + 6,
139 :
140 : // ARM Specific Register Types
141 : // ===========================
142 :
143 : //! Program pointer (PC) register (AArch64).
144 : kARM_PC = kPC,
145 : //! 32-bit general purpose register (R or W).
146 : kARM_GpW = kGp32,
147 : //! 64-bit general purpose register (X).
148 : kARM_GpX = kGp64,
149 : //! 8-bit view of VFP/ASIMD register (B).
150 : kARM_VecB = kVec8,
151 : //! 16-bit view of VFP/ASIMD register (H).
152 : kARM_VecH = kVec16,
153 : //! 32-bit view of VFP/ASIMD register (S).
154 : kARM_VecS = kVec32,
155 : //! 64-bit view of VFP/ASIMD register (D).
156 : kARM_VecD = kVec64,
157 : //! 128-bit view of VFP/ASIMD register (Q|V).
158 : kARM_VecV = kVec128,
159 :
160 : //! Maximum value of `RegType`.
161 : kMaxValue = 31
162 : };
163 : ASMJIT_DEFINE_ENUM_COMPARE(RegType)
164 :
165 : //! Register group.
166 : //!
167 : //! Provides a unique value that identifies groups of registers and their views.
168 : enum class RegGroup : uint8_t {
169 : //! General purpose register group compatible with all backends.
170 : kGp = 0,
171 : //! Vector register group compatible with all backends.
172 : //!
173 : //! Describes X86 XMM|YMM|ZMM registers ARM/AArch64 V registers.
174 : kVec = 1,
175 :
176 : //! Extra virtual group #2 that can be used by Compiler for register allocation.
177 : kExtraVirt2 = 2,
178 : //! Extra virtual group #3 that can be used by Compiler for register allocation.
179 : kExtraVirt3 = 3,
180 :
181 : //! Program counter group.
182 : kPC = 4,
183 :
184 : //! Extra non-virtual group that can be used by registers not managed by Compiler.
185 : kExtraNonVirt = 5,
186 :
187 : // X86 Specific Register Groups
188 : // ----------------------------
189 :
190 : //! K register group (KReg) - maps to \ref RegGroup::kExtraVirt2 (X86, X86_64).
191 : kX86_K = kExtraVirt2,
192 : //! MMX register group (MM) - maps to \ref RegGroup::kExtraVirt3 (X86, X86_64).
193 : kX86_MM = kExtraVirt3,
194 :
195 : //! Instruction pointer (X86, X86_64).
196 : kX86_Rip = kPC,
197 : //! Segment register group (X86, X86_64).
198 : kX86_SReg = kExtraNonVirt + 0,
199 : //! CR register group (X86, X86_64).
200 : kX86_CReg = kExtraNonVirt + 1,
201 : //! DR register group (X86, X86_64).
202 : kX86_DReg = kExtraNonVirt + 2,
203 : //! FPU register group (X86, X86_64).
204 : kX86_St = kExtraNonVirt + 3,
205 : //! BND register group (X86, X86_64).
206 : kX86_Bnd = kExtraNonVirt + 4,
207 : //! TMM register group (X86, X86_64).
208 : kX86_Tmm = kExtraNonVirt + 5,
209 :
210 : //! First group - only used in loops.
211 : k0 = 0,
212 : //! Last value of a virtual register that is managed by \ref BaseCompiler.
213 : kMaxVirt = Globals::kNumVirtGroups - 1,
214 : //! Maximum value of `RegGroup`.
215 : kMaxValue = 15
216 : };
217 0 : ASMJIT_DEFINE_ENUM_COMPARE(RegGroup)
218 :
219 : typedef Support::EnumValues<RegGroup, RegGroup::kGp, RegGroup::kMaxVirt> RegGroupVirtValues;
220 :
221 : //! Operand signature is a 32-bit number describing \ref Operand and some of its payload.
222 : //!
223 : //! In AsmJit operand signature is used to store additional payload of register, memory, and immediate operands.
224 : //! In practice the biggest pressure on OperandSignature is from \ref BaseMem and architecture specific memory
225 : //! operands that need to store additional payload that cannot be stored elsewhere as values of all other members
226 : //! are fully specified by \ref BaseMem.
227 : struct OperandSignature {
228 : //! \name Constants
229 : //! \{
230 :
231 : enum : uint32_t {
232 : // Operand type (3 least significant bits).
233 : // |........|........|........|.....XXX|
234 : kOpTypeShift = 0,
235 : kOpTypeMask = 0x07u << kOpTypeShift,
236 :
237 : // Register type (5 bits).
238 : // |........|........|........|XXXXX...|
239 : kRegTypeShift = 3,
240 : kRegTypeMask = 0x1Fu << kRegTypeShift,
241 :
242 : // Register group (4 bits).
243 : // |........|........|....XXXX|........|
244 : kRegGroupShift = 8,
245 : kRegGroupMask = 0x0Fu << kRegGroupShift,
246 :
247 : // Memory base type (5 bits).
248 : // |........|........|........|XXXXX...|
249 : kMemBaseTypeShift = 3,
250 : kMemBaseTypeMask = 0x1Fu << kMemBaseTypeShift,
251 :
252 : // Memory index type (5 bits).
253 : // |........|........|...XXXXX|........|
254 : kMemIndexTypeShift = 8,
255 : kMemIndexTypeMask = 0x1Fu << kMemIndexTypeShift,
256 :
257 : // Memory base+index combined (10 bits).
258 : // |........|........|...XXXXX|XXXXX...|
259 : kMemBaseIndexShift = 3,
260 : kMemBaseIndexMask = 0x3FFu << kMemBaseIndexShift,
261 :
262 : // This memory operand represents a home-slot or stack (Compiler) (1 bit).
263 : // |........|........|..X.....|........|
264 : kMemRegHomeShift = 13,
265 : kMemRegHomeFlag = 0x01u << kMemRegHomeShift,
266 :
267 : // Immediate type (1 bit).
268 : // |........|........|........|....X...|
269 : kImmTypeShift = 3,
270 : kImmTypeMask = 0x01u << kImmTypeShift,
271 :
272 : // Predicate used by either registers or immediate values (4 bits).
273 : // |........|XXXX....|........|........|
274 : kPredicateShift = 20,
275 : kPredicateMask = 0x0Fu << kPredicateShift,
276 :
277 : // Operand size (8 most significant bits).
278 : // |XXXXXXXX|........|........|........|
279 : kSizeShift = 24,
280 : kSizeMask = 0xFFu << kSizeShift
281 : };
282 :
283 : //! \}
284 :
285 : //! \name Members
286 : //! \{
287 :
288 : uint32_t _bits;
289 :
290 : //! \}
291 :
292 : //! \name Overloaded Operators
293 : //!
294 : //! Overloaded operators make `OperandSignature` behave like regular integer.
295 : //!
296 : //! \{
297 :
298 : inline constexpr bool operator!() const noexcept { return _bits != 0; }
299 : inline constexpr explicit operator bool() const noexcept { return _bits != 0; }
300 :
301 : inline OperandSignature& operator|=(uint32_t x) noexcept { _bits |= x; return *this; }
302 71131 : inline OperandSignature& operator&=(uint32_t x) noexcept { _bits &= x; return *this; }
303 : inline OperandSignature& operator^=(uint32_t x) noexcept { _bits ^= x; return *this; }
304 :
305 : inline OperandSignature& operator|=(const OperandSignature& other) noexcept { return operator|=(other._bits); }
306 : inline OperandSignature& operator&=(const OperandSignature& other) noexcept { return operator&=(other._bits); }
307 : inline OperandSignature& operator^=(const OperandSignature& other) noexcept { return operator^=(other._bits); }
308 :
309 : inline constexpr OperandSignature operator~() const noexcept { return OperandSignature{~_bits}; }
310 :
311 : inline constexpr OperandSignature operator|(uint32_t x) const noexcept { return OperandSignature{_bits | x}; }
312 1970 : inline constexpr OperandSignature operator&(uint32_t x) const noexcept { return OperandSignature{_bits & x}; }
313 : inline constexpr OperandSignature operator^(uint32_t x) const noexcept { return OperandSignature{_bits ^ x}; }
314 :
315 197089 : inline constexpr OperandSignature operator|(const OperandSignature& other) const noexcept { return OperandSignature{_bits | other._bits}; }
316 : inline constexpr OperandSignature operator&(const OperandSignature& other) const noexcept { return OperandSignature{_bits & other._bits}; }
317 : inline constexpr OperandSignature operator^(const OperandSignature& other) const noexcept { return OperandSignature{_bits ^ other._bits}; }
318 :
319 1970 : inline constexpr bool operator==(uint32_t x) const noexcept { return _bits == x; }
320 551203 : inline constexpr bool operator!=(uint32_t x) const noexcept { return _bits != x; }
321 :
322 1162590 : inline constexpr bool operator==(const OperandSignature& other) const noexcept { return _bits == other._bits; }
323 : inline constexpr bool operator!=(const OperandSignature& other) const noexcept { return _bits != other._bits; }
324 :
325 : //! \}
326 :
327 : //! \name Accessors
328 : //! \{
329 :
330 1176164 : inline void reset() noexcept { _bits = 0; }
331 :
332 : inline constexpr uint32_t bits() const noexcept { return _bits; }
333 : inline void setBits(uint32_t bits) noexcept { _bits = bits; }
334 :
335 : template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value>
336 : inline constexpr bool hasField() const noexcept {
337 355164 : return (_bits & kFieldMask) != 0;
338 : }
339 :
340 : template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value>
341 : inline constexpr bool hasField(uint32_t value) const noexcept {
342 : return (_bits & kFieldMask) != value << kFieldShift;
343 : }
344 :
345 : template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value>
346 : inline constexpr uint32_t getField() const noexcept {
347 7014257 : return (_bits >> kFieldShift) & (kFieldMask >> kFieldShift);
348 : }
349 :
350 : template<uint32_t kFieldMask, uint32_t kFieldShift = Support::ConstCTZ<kFieldMask>::value>
351 : inline void setField(uint32_t value) noexcept {
352 : ASMJIT_ASSERT((value & ~(kFieldMask >> kFieldShift)) == 0);
353 119547 : _bits = (_bits & ~kFieldMask) | (value << kFieldShift);
354 : }
355 :
356 862649 : inline constexpr OperandSignature subset(uint32_t mask) const noexcept { return OperandSignature{_bits & mask}; }
357 :
358 : template<uint32_t kFieldMask>
359 : inline constexpr bool matchesSignature(const OperandSignature& signature) const noexcept {
360 : return (_bits & kFieldMask) == signature._bits;
361 : }
362 :
363 : template<uint32_t kFieldMask>
364 : inline constexpr bool matchesFields(uint32_t bits) const noexcept {
365 : return (_bits & kFieldMask) == bits;
366 : }
367 :
368 : template<uint32_t kFieldMask>
369 : inline constexpr bool matchesFields(const OperandSignature& fields) const noexcept {
370 : return (_bits & kFieldMask) == fields._bits;
371 : }
372 :
373 389876 : inline constexpr bool isValid() const noexcept { return _bits != 0; }
374 :
375 : inline constexpr OperandType opType() const noexcept { return (OperandType)getField<kOpTypeMask>(); }
376 :
377 102060 : inline constexpr RegType regType() const noexcept { return (RegType)getField<kRegTypeMask>(); }
378 662273 : inline constexpr RegGroup regGroup() const noexcept { return (RegGroup)getField<kRegGroupMask>(); }
379 :
380 0 : inline constexpr RegType memBaseType() const noexcept { return (RegType)getField<kMemBaseTypeMask>(); }
381 0 : inline constexpr RegType memIndexType() const noexcept { return (RegType)getField<kMemIndexTypeMask>(); }
382 :
383 : inline constexpr uint32_t predicate() const noexcept { return getField<kPredicateMask>(); }
384 : inline constexpr uint32_t size() const noexcept { return getField<kSizeMask>(); }
385 :
386 : inline void setOpType(OperandType opType) noexcept { setField<kOpTypeMask>(uint32_t(opType)); }
387 : inline void setRegType(RegType regType) noexcept { setField<kRegTypeMask>(uint32_t(regType)); }
388 : inline void setRegGroup(RegGroup regGroup) noexcept { setField<kRegGroupMask>(uint32_t(regGroup)); }
389 :
390 : inline void setMemBaseType(RegGroup baseType) noexcept { setField<kMemBaseTypeMask>(uint32_t(baseType)); }
391 : inline void setMemIndexType(RegGroup indexType) noexcept { setField<kMemIndexTypeMask>(uint32_t(indexType)); }
392 :
393 : inline void setPredicate(uint32_t predicate) noexcept { setField<kPredicateMask>(predicate); }
394 : inline void setSize(uint32_t size) noexcept { setField<kSizeMask>(size); }
395 :
396 : //! \}
397 :
398 : //! \name Static Constructors
399 : //! \{
400 :
401 : static inline constexpr OperandSignature fromBits(uint32_t bits) noexcept {
402 : return OperandSignature{bits};
403 : }
404 :
405 : template<uint32_t kFieldMask, typename T>
406 : static inline constexpr OperandSignature fromValue(const T& value) noexcept {
407 : return OperandSignature{uint32_t(value) << Support::ConstCTZ<kFieldMask>::value};
408 : }
409 :
410 : static inline constexpr OperandSignature fromOpType(OperandType opType) noexcept {
411 : return OperandSignature{uint32_t(opType) << kOpTypeShift};
412 : }
413 :
414 : static inline constexpr OperandSignature fromRegType(RegType regType) noexcept {
415 : return OperandSignature{uint32_t(regType) << kRegTypeShift};
416 : }
417 :
418 : static inline constexpr OperandSignature fromRegGroup(RegGroup regGroup) noexcept {
419 : return OperandSignature{uint32_t(regGroup) << kRegGroupShift};
420 : }
421 :
422 : static inline constexpr OperandSignature fromRegTypeAndGroup(RegType regType, RegGroup regGroup) noexcept {
423 : return fromRegType(regType) | fromRegGroup(regGroup);
424 : }
425 :
426 : static inline constexpr OperandSignature fromMemBaseType(RegType baseType) noexcept {
427 197089 : return OperandSignature{uint32_t(baseType) << kMemBaseTypeShift};
428 : }
429 :
430 : static inline constexpr OperandSignature fromMemIndexType(RegType indexType) noexcept {
431 : return OperandSignature{uint32_t(indexType) << kMemIndexTypeShift};
432 : }
433 :
434 : static inline constexpr OperandSignature fromPredicate(uint32_t predicate) noexcept {
435 : return OperandSignature{predicate << kPredicateShift};
436 : }
437 :
438 : static inline constexpr OperandSignature fromSize(uint32_t size) noexcept {
439 54984 : return OperandSignature{size << kSizeShift};
440 : }
441 :
442 : //! \}
443 : };
444 :
445 : //! Base class representing an operand in AsmJit (non-default constructed version).
446 : //!
447 : //! Contains no initialization code and can be used safely to define an array of operands that won't be initialized.
448 : //! This is a \ref Operand base structure designed to be statically initialized, static const, or to be used by user
449 : //! code to define an array of operands without having them default initialized at construction time.
450 : //!
451 : //! The key difference between \ref Operand and \ref Operand_ is:
452 : //!
453 : //! ```
454 : //! Operand_ xArray[10]; // Not initialized, contains garbage.
455 : //! Operand_ yArray[10] {}; // All operands initialized to none explicitly (zero initialized).
456 : //! Operand yArray[10]; // All operands initialized to none implicitly (zero initialized).
457 : //! ```
458 : struct Operand_ {
459 : //! \name Types
460 : //! \{
461 :
462 : typedef OperandSignature Signature;
463 :
464 : //! \}
465 :
466 : //! \name Constants
467 : //! \{
468 :
469 : // Indexes to `_data` array.
470 : enum DataIndex : uint32_t {
471 : kDataMemIndexId = 0,
472 : kDataMemOffsetLo = 1,
473 :
474 : kDataImmValueLo = ASMJIT_ARCH_LE ? 0 : 1,
475 : kDataImmValueHi = ASMJIT_ARCH_LE ? 1 : 0
476 : };
477 :
478 : //! Constants useful for VirtId <-> Index translation.
479 : enum VirtIdConstants : uint32_t {
480 : //! Minimum valid packed-id.
481 : kVirtIdMin = 256,
482 : //! Maximum valid packed-id, excludes Globals::kInvalidId.
483 : kVirtIdMax = Globals::kInvalidId - 1,
484 : //! Count of valid packed-ids.
485 : kVirtIdCount = uint32_t(kVirtIdMax - kVirtIdMin + 1)
486 : };
487 :
488 : //! \}
489 :
490 : //! \name Members
491 : //! \{
492 :
493 : //! Provides operand type and additional payload.
494 : Signature _signature;
495 : //! Either base id as used by memory operand or any id as used by others.
496 : uint32_t _baseId;
497 :
498 : //! Data specific to the operand type.
499 : //!
500 : //! The reason we don't use union is that we have `constexpr` constructors that construct operands and other
501 : //!`constexpr` functions that return whether another Operand or something else. These cannot generally work with
502 : //! unions so we also cannot use `union` if we want to be standard compliant.
503 : uint32_t _data[2];
504 :
505 : //! \}
506 :
507 : //! Tests whether the given `id` is a valid virtual register id. Since AsmJit supports both physical and virtual
508 : //! registers it must be able to distinguish between these two. The idea is that physical registers are always
509 : //! limited in size, so virtual identifiers start from `kVirtIdMin` and end at `kVirtIdMax`.
510 0 : static inline bool isVirtId(uint32_t id) noexcept { return id - kVirtIdMin < uint32_t(kVirtIdCount); }
511 : //! Converts a real-id into a packed-id that can be stored in Operand.
512 273777 : static inline uint32_t indexToVirtId(uint32_t id) noexcept { return id + kVirtIdMin; }
513 : //! Converts a packed-id back to real-id.
514 273777 : static inline uint32_t virtIdToIndex(uint32_t id) noexcept { return id - kVirtIdMin; }
515 :
516 : //! \name Construction & Destruction
517 : //! \{
518 :
519 : //! \cond INTERNAL
520 : //! Initializes a `BaseReg` operand from `signature` and register `id`.
521 : inline void _initReg(const Signature& signature, uint32_t id) noexcept {
522 273777 : _signature = signature;
523 273777 : _baseId = id;
524 273777 : _data[0] = 0;
525 273777 : _data[1] = 0;
526 : }
527 : //! \endcond
528 :
529 : //! Initializes the operand from `other` operand (used by operator overloads).
530 1213866 : inline void copyFrom(const Operand_& other) noexcept { memcpy(this, &other, sizeof(Operand_)); }
531 :
532 : //! Resets the `Operand` to none.
533 : //!
534 : //! None operand is defined the following way:
535 : //! - Its signature is zero (OperandType::kNone, and the rest zero as well).
536 : //! - Its id is `0`.
537 : //! - The reserved8_4 field is set to `0`.
538 : //! - The reserved12_4 field is set to zero.
539 : //!
540 : //! In other words, reset operands have all members set to zero. Reset operand must match the Operand state
541 : //! right after its construction. Alternatively, if you have an array of operands, you can simply use `memset()`.
542 : //!
543 : //! ```
544 : //! using namespace asmjit;
545 : //!
546 : //! Operand a;
547 : //! Operand b;
548 : //! assert(a == b);
549 : //!
550 : //! b = x86::eax;
551 : //! assert(a != b);
552 : //!
553 : //! b.reset();
554 : //! assert(a == b);
555 : //!
556 : //! memset(&b, 0, sizeof(Operand));
557 : //! assert(a == b);
558 : //! ```
559 : inline void reset() noexcept {
560 : _signature.reset();
561 1176164 : _baseId = 0;
562 1176164 : _data[0] = 0;
563 1176164 : _data[1] = 0;
564 : }
565 :
566 : //! \}
567 :
568 : //! \name Overloaded Operators
569 : //! \{
570 :
571 : //! Tests whether this operand is the same as `other`.
572 30807 : inline constexpr bool operator==(const Operand_& other) const noexcept { return equals(other); }
573 : //! Tests whether this operand is not the same as `other`.
574 : inline constexpr bool operator!=(const Operand_& other) const noexcept { return !equals(other); }
575 :
576 : //! \}
577 :
578 : //! \name Cast
579 : //! \{
580 :
581 : //! Casts this operand to `T` type.
582 : template<typename T>
583 : inline T& as() noexcept { return static_cast<T&>(*this); }
584 :
585 : //! Casts this operand to `T` type (const).
586 : template<typename T>
587 : inline const T& as() const noexcept { return static_cast<const T&>(*this); }
588 :
589 : //! \}
590 :
591 : //! \name Accessors
592 : //! \{
593 :
594 : //! Tests whether the operand's signature matches the signature of the `other` operand.
595 : inline constexpr bool hasSignature(const Operand_& other) const noexcept { return _signature == other._signature; }
596 : //! Tests whether the operand's signature matches the given signature `sign`.
597 : inline constexpr bool hasSignature(const Signature& other) const noexcept { return _signature == other; }
598 :
599 : //! Returns operand signature as unsigned 32-bit integer.
600 : //!
601 : //! Signature is first 4 bytes of the operand data. It's used mostly for operand checking as it's
602 : //! much faster to check packed 4 bytes at once than having to check these bytes individually.
603 0 : inline constexpr Signature signature() const noexcept { return _signature; }
604 :
605 : //! Sets the operand signature, see `signature()`.
606 : //!
607 : //! \note Improper use of `setSignature()` can lead to hard-to-debug errors.
608 0 : inline void setSignature(const Signature& signature) noexcept { _signature = signature; }
609 :
610 : //! Returns the type of the operand, see `OpType`.
611 : inline constexpr OperandType opType() const noexcept { return _signature.opType(); }
612 : //! Tests whether the operand is none (`OperandType::kNone`).
613 : inline constexpr bool isNone() const noexcept { return _signature == Signature::fromBits(0); }
614 : //! Tests whether the operand is a register (`OperandType::kReg`).
615 : inline constexpr bool isReg() const noexcept { return opType() == OperandType::kReg; }
616 : //! Tests whether the operand is a memory location (`OperandType::kMem`).
617 0 : inline constexpr bool isMem() const noexcept { return opType() == OperandType::kMem; }
618 : //! Tests whether the operand is an immediate (`OperandType::kImm`).
619 : inline constexpr bool isImm() const noexcept { return opType() == OperandType::kImm; }
620 : //! Tests whether the operand is a label (`OperandType::kLabel`).
621 : inline constexpr bool isLabel() const noexcept { return opType() == OperandType::kLabel; }
622 :
623 : //! Tests whether the operand is a physical register.
624 : inline constexpr bool isPhysReg() const noexcept { return isReg() && _baseId < 0xFFu; }
625 : //! Tests whether the operand is a virtual register.
626 : inline constexpr bool isVirtReg() const noexcept { return isReg() && _baseId > 0xFFu; }
627 :
628 : //! Tests whether the operand specifies a size (i.e. the size is not zero).
629 : inline constexpr bool hasSize() const noexcept { return _signature.hasField<Signature::kSizeMask>(); }
630 : //! Tests whether the size of the operand matches `size`.
631 : inline constexpr bool hasSize(uint32_t s) const noexcept { return size() == s; }
632 :
633 : //! Returns the size of the operand in bytes.
634 : //!
635 : //! The value returned depends on the operand type:
636 : //! * None - Should always return zero size.
637 : //! * Reg - Should always return the size of the register. If the register size depends on architecture
638 : //! (like `x86::CReg` and `x86::DReg`) the size returned should be the greatest possible (so it
639 : //! should return 64-bit size in such case).
640 : //! * Mem - Size is optional and will be in most cases zero.
641 : //! * Imm - Should always return zero size.
642 : //! * Label - Should always return zero size.
643 : inline constexpr uint32_t size() const noexcept { return _signature.getField<Signature::kSizeMask>(); }
644 :
645 : //! Returns the operand id.
646 : //!
647 : //! The value returned should be interpreted accordingly to the operand type:
648 : //! * None - Should be `0`.
649 : //! * Reg - Physical or virtual register id.
650 : //! * Mem - Multiple meanings - BASE address (register or label id), or high value of a 64-bit absolute address.
651 : //! * Imm - Should be `0`.
652 : //! * Label - Label id if it was created by using `newLabel()` or `Globals::kInvalidId` if the label is invalid or
653 : //! not initialized.
654 1208200 : inline constexpr uint32_t id() const noexcept { return _baseId; }
655 :
656 : //! Tests whether the operand is 100% equal to `other` operand.
657 : //!
658 : //! \note This basically performs a binary comparison, if aby bit is
659 : //! different the operands are not equal.
660 30807 : inline constexpr bool equals(const Operand_& other) const noexcept {
661 : return (_signature == other._signature) &
662 30807 : (_baseId == other._baseId ) &
663 30807 : (_data[0] == other._data[0] ) &
664 30807 : (_data[1] == other._data[1] ) ;
665 : }
666 :
667 : //! Tests whether the operand is a register matching the given register `type`.
668 : inline constexpr bool isReg(RegType type) const noexcept {
669 : return _signature.subset(Signature::kOpTypeMask | Signature::kRegTypeMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegType(type));
670 : }
671 :
672 : //! Tests whether the operand is register and of register `type` and `id`.
673 : inline constexpr bool isReg(RegType type, uint32_t id) const noexcept {
674 : return isReg(type) && this->id() == id;
675 : }
676 :
677 : //! Tests whether the operand is a register or memory.
678 : inline constexpr bool isRegOrMem() const noexcept {
679 : return Support::isBetween<uint32_t>(uint32_t(opType()), uint32_t(OperandType::kReg), uint32_t(OperandType::kMem));
680 : }
681 :
682 : //! \}
683 : };
684 :
685 : //! Base class representing an operand in AsmJit (default constructed version).
686 : class Operand : public Operand_ {
687 : public:
688 : //! \name Construction & Destruction
689 : //! \{
690 :
691 : //! Creates `kOpNone` operand having all members initialized to zero.
692 : inline constexpr Operand() noexcept
693 54984 : : Operand_{ Signature::fromOpType(OperandType::kNone), 0u, { 0u, 0u }} {}
694 :
695 : //! Creates a cloned `other` operand.
696 : inline constexpr Operand(const Operand& other) noexcept = default;
697 :
698 : //! Creates a cloned `other` operand.
699 : inline constexpr explicit Operand(const Operand_& other)
700 50221 : : Operand_(other) {}
701 :
702 : //! Creates an operand initialized to raw `[u0, u1, u2, u3]` values.
703 : inline constexpr Operand(Globals::Init_, const Signature& u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept
704 464297 : : Operand_{ u0, u1, { u2, u3 }} {}
705 :
706 : //! Creates an uninitialized operand (dangerous).
707 : inline explicit Operand(Globals::NoInit_) noexcept {}
708 :
709 : //! \}
710 :
711 : //! \name Overloaded Operators
712 : //! \{
713 :
714 : inline Operand& operator=(const Operand& other) noexcept = default;
715 94 : inline Operand& operator=(const Operand_& other) noexcept { return operator=(static_cast<const Operand&>(other)); }
716 :
717 : //! \}
718 :
719 : //! \name Clone
720 : //! \{
721 :
722 : //! Clones this operand and returns its copy.
723 : inline constexpr Operand clone() const noexcept { return Operand(*this); }
724 :
725 : //! \}
726 : };
727 :
728 : static_assert(sizeof(Operand) == 16, "asmjit::Operand must be exactly 16 bytes long");
729 :
730 : //! Label (jump target or data location).
731 : //!
732 : //! Label represents a location in code typically used as a jump target, but may be also a reference to some data or
733 : //! a static variable. Label has to be explicitly created by BaseEmitter.
734 : //!
735 : //! Example of using labels:
736 : //!
737 : //! ```
738 : //! // Create some emitter (for example x86::Assembler).
739 : //! x86::Assembler a;
740 : //!
741 : //! // Create Label instance.
742 : //! Label L1 = a.newLabel();
743 : //!
744 : //! // ... your code ...
745 : //!
746 : //! // Using label.
747 : //! a.jump(L1);
748 : //!
749 : //! // ... your code ...
750 : //!
751 : //! // Bind label to the current position, see `BaseEmitter::bind()`.
752 : //! a.bind(L1);
753 : //! ```
754 : class Label : public Operand {
755 : public:
756 : //! \name Construction & Destruction
757 : //! \{
758 :
759 : //! Creates a label operand without ID (you must set the ID to make it valid).
760 : inline constexpr Label() noexcept
761 : : Operand(Globals::Init, Signature::fromOpType(OperandType::kLabel), Globals::kInvalidId, 0, 0) {}
762 :
763 : //! Creates a cloned label operand of `other`.
764 : inline constexpr Label(const Label& other) noexcept
765 0 : : Operand(other) {}
766 :
767 : //! Creates a label operand of the given `id`.
768 : inline constexpr explicit Label(uint32_t id) noexcept
769 : : Operand(Globals::Init, Signature::fromOpType(OperandType::kLabel), id, 0, 0) {}
770 :
771 : inline explicit Label(Globals::NoInit_) noexcept
772 : : Operand(Globals::NoInit) {}
773 :
774 : //! Resets the label, will reset all properties and set its ID to `Globals::kInvalidId`.
775 : inline void reset() noexcept {
776 : _signature = Signature::fromOpType(OperandType::kLabel);
777 : _baseId = Globals::kInvalidId;
778 : _data[0] = 0;
779 : _data[1] = 0;
780 : }
781 :
782 : //! \}
783 :
784 : //! \name Overloaded Operators
785 : //! \{
786 :
787 : inline Label& operator=(const Label& other) noexcept = default;
788 :
789 : //! \}
790 :
791 : //! \name Accessors
792 : //! \{
793 :
794 : //! Tests whether the label was created by CodeHolder and/or an attached emitter.
795 : inline constexpr bool isValid() const noexcept { return _baseId != Globals::kInvalidId; }
796 : //! Sets the label `id`.
797 : inline void setId(uint32_t id) noexcept { _baseId = id; }
798 :
799 : //! \}
800 : };
801 :
802 : //! \cond INTERNAL
803 : //! Default register traits.
804 : struct BaseRegTraits {
805 : enum : uint32_t {
806 : //! \ref TypeId representing this register type, could be \ref TypeId::kVoid if such type doesn't exist.
807 : kTypeId = uint32_t(TypeId::kVoid),
808 : //! RegType is not valid by default.
809 : kValid = 0,
810 : //! Count of registers (0 if none).
811 : kCount = 0,
812 :
813 : //! Zero type by default (defeaults to None).
814 : kType = uint32_t(RegType::kNone),
815 : //! Zero group by default (defaults to GP).
816 : kGroup = uint32_t(RegGroup::kGp),
817 : //! No size by default.
818 : kSize = 0,
819 :
820 : //! Empty signature by default (not even having operand type set to register).
821 : kSignature = 0
822 : };
823 : };
824 : //! \endcond
825 :
826 : //! Physical or virtual register operand.
827 : class BaseReg : public Operand {
828 : public:
829 : //! \name Constants
830 : //! \{
831 :
832 : enum : uint32_t {
833 : //! None or any register (mostly internal).
834 : kIdBad = 0xFFu,
835 :
836 : kBaseSignatureMask =
837 : Signature::kOpTypeMask |
838 : Signature::kRegTypeMask |
839 : Signature::kRegGroupMask |
840 : Signature::kSizeMask,
841 :
842 : kTypeNone = uint32_t(RegType::kNone),
843 : kSignature = Signature::fromOpType(OperandType::kReg).bits()
844 : };
845 :
846 : //! \}
847 :
848 : //! \name Construction & Destruction
849 : //! \{
850 :
851 : //! Creates a dummy register operand.
852 : inline constexpr BaseReg() noexcept
853 : : Operand(Globals::Init, Signature::fromOpType(OperandType::kReg), kIdBad, 0, 0) {}
854 :
855 : //! Creates a new register operand which is the same as `other` .
856 : inline constexpr BaseReg(const BaseReg& other) noexcept
857 54984 : : Operand(other) {}
858 :
859 : //! Creates a new register operand compatible with `other`, but with a different `id`.
860 : inline constexpr BaseReg(const BaseReg& other, uint32_t id) noexcept
861 : : Operand(Globals::Init, other._signature, id, 0, 0) {}
862 :
863 : //! Creates a register initialized to the given `signature` and `id`.
864 : inline constexpr BaseReg(const Signature& signature, uint32_t id) noexcept
865 : : Operand(Globals::Init, signature, id, 0, 0) {}
866 :
867 : inline explicit BaseReg(Globals::NoInit_) noexcept
868 : : Operand(Globals::NoInit) {}
869 :
870 : //! \}
871 :
872 : //! \name Overloaded Operators
873 : //! \{
874 :
875 : inline BaseReg& operator=(const BaseReg& other) noexcept = default;
876 :
877 : //! \}
878 :
879 : //! \name Accessors
880 : //! \{
881 :
882 : //! Returns base signature of the register associated with each register type.
883 : //!
884 : //! Base signature only contains the operand type, register type, register group, and register size. It doesn't
885 : //! contain element type, predicate, or other architecture-specific data. Base signature is a signature that is
886 : //! provided by architecture-specific `RegTraits`, like \ref x86::RegTraits.
887 : inline constexpr OperandSignature baseSignature() const noexcept { return _signature & kBaseSignatureMask; }
888 :
889 : //! Tests whether the operand's base signature matches the given signature `sign`.
890 : inline constexpr bool hasBaseSignature(uint32_t signature) const noexcept { return baseSignature() == signature; }
891 : //! Tests whether the operand's base signature matches the given signature `sign`.
892 : inline constexpr bool hasBaseSignature(const OperandSignature& signature) const noexcept { return baseSignature() == signature; }
893 : //! Tests whether the operand's base signature matches the base signature of the `other` operand.
894 : inline constexpr bool hasBaseSignature(const BaseReg& other) const noexcept { return baseSignature() == other.baseSignature(); }
895 :
896 : //! Tests whether this register is the same as `other`.
897 : //!
898 : //! This is just an optimization. Registers by default only use the first 8 bytes of Operand data, so this method
899 : //! takes advantage of this knowledge and only compares these 8 bytes. If both operands were created correctly
900 : //! both \ref equals() and \ref isSame() should give the same answer, however, if any of these two contains garbage
901 : //! or other metadata in the upper 8 bytes then \ref isSame() may return `true` in cases in which \ref equals()
902 : //! returns false.
903 : inline constexpr bool isSame(const BaseReg& other) const noexcept {
904 : return (_signature == other._signature) & (_baseId == other._baseId);
905 : }
906 :
907 : //! Tests whether the register is valid (either virtual or physical).
908 : inline constexpr bool isValid() const noexcept { return (_signature != 0) & (_baseId != kIdBad); }
909 :
910 : //! Tests whether this is a physical register.
911 : inline constexpr bool isPhysReg() const noexcept { return _baseId < kIdBad; }
912 : //! Tests whether this is a virtual register.
913 0 : inline constexpr bool isVirtReg() const noexcept { return _baseId > kIdBad; }
914 :
915 : //! Tests whether the register type matches `type` - same as `isReg(type)`, provided for convenience.
916 : inline constexpr bool isType(RegType type) const noexcept { return _signature.subset(Signature::kRegTypeMask) == Signature::fromRegType(type); }
917 : //! Tests whether the register group matches `group`.
918 : inline constexpr bool isGroup(RegGroup group) const noexcept { return _signature.subset(Signature::kRegGroupMask) == Signature::fromRegGroup(group); }
919 :
920 : //! Tests whether the register is a general purpose register (any size).
921 : inline constexpr bool isGp() const noexcept { return isGroup(RegGroup::kGp); }
922 : //! Tests whether the register is a vector register.
923 : inline constexpr bool isVec() const noexcept { return isGroup(RegGroup::kVec); }
924 :
925 : using Operand_::isReg;
926 :
927 : //! Same as `isType()`, provided for convenience.
928 : inline constexpr bool isReg(RegType rType) const noexcept { return isType(rType); }
929 : //! Tests whether the register type matches `type` and register id matches `id`.
930 : inline constexpr bool isReg(RegType rType, uint32_t id) const noexcept { return isType(rType) && this->id() == id; }
931 :
932 : //! Returns the register type.
933 : inline constexpr RegType type() const noexcept { return _signature.regType(); }
934 : //! Returns the register group.
935 : inline constexpr RegGroup group() const noexcept { return _signature.regGroup(); }
936 :
937 : //! Returns operation predicate of the register (ARM/AArch64).
938 : //!
939 : //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp
940 : //! of the register.
941 : inline constexpr uint32_t predicate() const noexcept { return _signature.getField<Signature::kPredicateMask>(); }
942 :
943 : //! Sets operation predicate of the register to `predicate` (ARM/AArch64).
944 : //!
945 : //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp
946 : //! of the register.
947 : inline void setPredicate(uint32_t predicate) noexcept { _signature.setField<Signature::kPredicateMask>(predicate); }
948 :
949 : //! Resets shift operation type of the register to the default value (ARM/AArch64).
950 : inline void resetPredicate() noexcept { _signature.setField<Signature::kPredicateMask>(0); }
951 :
952 : //! Clones the register operand.
953 : inline constexpr BaseReg clone() const noexcept { return BaseReg(*this); }
954 :
955 : //! Casts this register to `RegT` by also changing its signature.
956 : //!
957 : //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors.
958 : template<typename RegT>
959 : inline constexpr RegT cloneAs() const noexcept { return RegT(Signature(RegT::kSignature), id()); }
960 :
961 : //! Casts this register to `other` by also changing its signature.
962 : //!
963 : //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors.
964 : template<typename RegT>
965 : inline constexpr RegT cloneAs(const RegT& other) const noexcept { return RegT(other.signature(), id()); }
966 :
967 : //! Sets the register id to `id`.
968 0 : inline void setId(uint32_t id) noexcept { _baseId = id; }
969 :
970 : //! Sets a 32-bit operand signature based on traits of `RegT`.
971 : template<typename RegT>
972 : inline void setSignatureT() noexcept { _signature = RegT::kSignature; }
973 :
974 : //! Sets the register `signature` and `id`.
975 : inline void setSignatureAndId(const OperandSignature& signature, uint32_t id) noexcept {
976 0 : _signature = signature;
977 0 : _baseId = id;
978 : }
979 :
980 : //! \}
981 :
982 : //! \name Static Functions
983 : //! \{
984 :
985 : //! Tests whether the `op` operand is a general purpose register.
986 : static inline bool isGp(const Operand_& op) noexcept {
987 : // Check operand type and register group. Not interested in register type and size.
988 : return op.signature().subset(Signature::kOpTypeMask | Signature::kRegGroupMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(RegGroup::kGp));
989 : }
990 :
991 : //! Tests whether the `op` operand is a vector register.
992 : static inline bool isVec(const Operand_& op) noexcept {
993 : // Check operand type and register group. Not interested in register type and size.
994 : return op.signature().subset(Signature::kOpTypeMask | Signature::kRegGroupMask) == (Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(RegGroup::kVec));
995 : }
996 :
997 : //! Tests whether the `op` is a general purpose register of the given `id`.
998 0 : static inline bool isGp(const Operand_& op, uint32_t id) noexcept { return isGp(op) & (op.id() == id); }
999 : //! Tests whether the `op` is a vector register of the given `id`.
1000 : static inline bool isVec(const Operand_& op, uint32_t id) noexcept { return isVec(op) & (op.id() == id); }
1001 :
1002 : //! \}
1003 : };
1004 :
1005 : //! RegOnly is 8-byte version of `BaseReg` that allows to store either register or nothing.
1006 : //!
1007 : //! It's designed to decrease the space consumed by an extra "operand" in \ref BaseEmitter and \ref InstNode.
1008 : struct RegOnly {
1009 : //! \name Types
1010 : //! \{
1011 :
1012 : typedef OperandSignature Signature;
1013 :
1014 : //! \}
1015 :
1016 : //! Operand signature - only \ref OperandType::kNone and \ref OperandType::kReg are supported.
1017 : Signature _signature;
1018 : //! Physical or virtual register id.
1019 : uint32_t _id;
1020 :
1021 : //! \name Construction & Destruction
1022 : //! \{
1023 :
1024 : //! Initializes the `RegOnly` instance to hold register `signature` and `id`.
1025 : inline void init(const OperandSignature& signature, uint32_t id) noexcept {
1026 1558397 : _signature = signature;
1027 784018 : _id = id;
1028 : }
1029 :
1030 : inline void init(const BaseReg& reg) noexcept { init(reg.signature(), reg.id()); }
1031 : inline void init(const RegOnly& reg) noexcept { init(reg.signature(), reg.id()); }
1032 :
1033 : //! Resets the `RegOnly` members to zeros (none).
1034 : inline void reset() noexcept { init(Signature::fromBits(0), 0); }
1035 :
1036 : //! \}
1037 :
1038 : //! \name Accessors
1039 : //! \{
1040 :
1041 : //! Tests whether this ExtraReg is none (same as calling `Operand_::isNone()`).
1042 : inline constexpr bool isNone() const noexcept { return _signature == 0; }
1043 : //! Tests whether the register is valid (either virtual or physical).
1044 : inline constexpr bool isReg() const noexcept { return _signature != 0; }
1045 :
1046 : //! Tests whether this is a physical register.
1047 0 : inline constexpr bool isPhysReg() const noexcept { return _id < BaseReg::kIdBad; }
1048 : //! Tests whether this is a virtual register (used by `BaseCompiler`).
1049 : inline constexpr bool isVirtReg() const noexcept { return _id > BaseReg::kIdBad; }
1050 :
1051 : //! Returns the register signature or 0 if no register is assigned.
1052 774379 : inline constexpr OperandSignature signature() const noexcept { return _signature; }
1053 : //! Returns the register id.
1054 : //!
1055 : //! \note Always check whether the register is assigned before using the returned identifier as
1056 : //! non-assigned `RegOnly` instance would return zero id, which is still a valid register id.
1057 1031021 : inline constexpr uint32_t id() const noexcept { return _id; }
1058 :
1059 : //! Sets the register id.
1060 : inline void setId(uint32_t id) noexcept { _id = id; }
1061 :
1062 : //! Returns the register type.
1063 : inline constexpr RegType type() const noexcept { return _signature.regType(); }
1064 : //! Returns the register group.
1065 : inline constexpr RegGroup group() const noexcept { return _signature.regGroup(); }
1066 :
1067 : //! \}
1068 :
1069 : //! \name Utilities
1070 : //! \{
1071 :
1072 : //! Converts this ExtraReg to a real `RegT` operand.
1073 : template<typename RegT>
1074 0 : inline constexpr RegT toReg() const noexcept { return RegT(_signature, _id); }
1075 :
1076 : //! \}
1077 : };
1078 :
1079 : //! \cond INTERNAL
1080 : //! Adds a template specialization for `REG_TYPE` into the local `RegTraits`.
1081 : #define ASMJIT_DEFINE_REG_TRAITS(REG, REG_TYPE, GROUP, SIZE, COUNT, TYPE_ID) \
1082 : template<> \
1083 : struct RegTraits<REG_TYPE> { \
1084 : typedef REG RegT; \
1085 : \
1086 : enum : uint32_t { \
1087 : kValid = uint32_t(true), \
1088 : kCount = uint32_t(COUNT), \
1089 : kType = uint32_t(REG_TYPE), \
1090 : kGroup = uint32_t(GROUP), \
1091 : kSize = uint32_t(SIZE), \
1092 : kTypeId = uint32_t(TYPE_ID), \
1093 : \
1094 : kSignature = (OperandSignature::fromOpType(OperandType::kReg) | \
1095 : OperandSignature::fromRegType(REG_TYPE) | \
1096 : OperandSignature::fromRegGroup(GROUP) | \
1097 : OperandSignature::fromSize(kSize)).bits(), \
1098 : }; \
1099 : }
1100 :
1101 : //! Adds constructors and member functions to a class that implements abstract register. Abstract register is register
1102 : //! that doesn't have type or signature yet, it's a base class like `x86::Reg` or `arm::Reg`.
1103 : #define ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \
1104 : public: \
1105 : /*! Default constructor that only setups basics. */ \
1106 : inline constexpr REG() noexcept \
1107 : : BASE(Signature{kSignature}, kIdBad) {} \
1108 : \
1109 : /*! Makes a copy of the `other` register operand. */ \
1110 : inline constexpr REG(const REG& other) noexcept \
1111 : : BASE(other) {} \
1112 : \
1113 : /*! Makes a copy of the `other` register having id set to `id` */ \
1114 : inline constexpr REG(const BaseReg& other, uint32_t id) noexcept \
1115 : : BASE(other, id) {} \
1116 : \
1117 : /*! Creates a register based on `signature` and `id`. */ \
1118 : inline constexpr REG(const OperandSignature& sgn, uint32_t id) noexcept \
1119 : : BASE(sgn, id) {} \
1120 : \
1121 : /*! Creates a completely uninitialized REG register operand (garbage). */ \
1122 : inline explicit REG(Globals::NoInit_) noexcept \
1123 : : BASE(Globals::NoInit) {} \
1124 : \
1125 : /*! Creates a new register from register type and id. */ \
1126 : static inline REG fromTypeAndId(RegType type, uint32_t id) noexcept { \
1127 : return REG(signatureOf(type), id); \
1128 : } \
1129 : \
1130 : /*! Clones the register operand. */ \
1131 : inline constexpr REG clone() const noexcept { return REG(*this); } \
1132 : \
1133 : inline REG& operator=(const REG& other) noexcept = default;
1134 :
1135 : //! Adds constructors and member functions to a class that implements final register. Final registers MUST HAVE a valid
1136 : //! signature.
1137 : #define ASMJIT_DEFINE_FINAL_REG(REG, BASE, TRAITS) \
1138 : public: \
1139 : enum : uint32_t { \
1140 : kThisType = TRAITS::kType, \
1141 : kThisGroup = TRAITS::kGroup, \
1142 : kThisSize = TRAITS::kSize, \
1143 : kSignature = TRAITS::kSignature \
1144 : }; \
1145 : \
1146 : ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE) \
1147 : \
1148 : /*! Creates a register operand having its id set to `id`. */ \
1149 : inline constexpr explicit REG(uint32_t id) noexcept \
1150 : : BASE(Signature{kSignature}, id) {}
1151 : //! \endcond
1152 :
1153 : //! Base class for all memory operands.
1154 : //!
1155 : //! The data is split into the following parts:
1156 : //!
1157 : //! - BASE - Base register or label - requires 36 bits total. 4 bits are used to encode the type of the BASE operand
1158 : //! (label vs. register type) and the remaining 32 bits define the BASE id, which can be a physical or virtual
1159 : //! register index. If BASE type is zero, which is never used as a register type and label doesn't use it as well
1160 : //! then BASE field contains a high DWORD of a possible 64-bit absolute address, which is possible on X64.
1161 : //!
1162 : //! - INDEX - Index register (or theoretically Label, which doesn't make sense). Encoding is similar to BASE - it
1163 : //! also requires 36 bits and splits the encoding to INDEX type (4 bits defining the register type) and 32-bit id.
1164 : //!
1165 : //! - OFFSET - A relative offset of the address. Basically if BASE is specified the relative displacement adjusts
1166 : //! BASE and an optional INDEX. if BASE is not specified then the OFFSET should be considered as ABSOLUTE address
1167 : //! (at least on X86). In that case its low 32 bits are stored in DISPLACEMENT field and the remaining high 32
1168 : //! bits are stored in BASE.
1169 : //!
1170 : //! - OTHER - There is rest 8 bits that can be used for whatever purpose. For example \ref x86::Mem operand uses
1171 : //! these bits to store segment override prefix and index shift (or scale).
1172 : class BaseMem : public Operand {
1173 : public:
1174 : //! \name Construction & Destruction
1175 : //! \{
1176 :
1177 : //! Creates a default `BaseMem` operand, that points to [0].
1178 : inline constexpr BaseMem() noexcept
1179 : : Operand(Globals::Init, Signature::fromOpType(OperandType::kMem), 0, 0, 0) {}
1180 :
1181 : //! Creates a `BaseMem` operand that is a clone of `other`.
1182 : inline constexpr BaseMem(const BaseMem& other) noexcept
1183 0 : : Operand(other) {}
1184 :
1185 : //! Creates a `BaseMem` operand from `baseReg` and `offset`.
1186 : //!
1187 : //! \note This is an architecture independent constructor that can be used to create an architecture
1188 : //! independent memory operand to be used in portable code that can handle multiple architectures.
1189 0 : inline constexpr explicit BaseMem(const BaseReg& baseReg, int32_t offset = 0) noexcept
1190 : : Operand(Globals::Init,
1191 : Signature::fromOpType(OperandType::kMem) | Signature::fromMemBaseType(baseReg.type()),
1192 : baseReg.id(),
1193 : 0,
1194 0 : uint32_t(offset)) {}
1195 :
1196 : //! \cond INTERNAL
1197 : //! Creates a `BaseMem` operand from 4 integers as used by `Operand_` struct.
1198 : inline constexpr BaseMem(const OperandSignature& u0, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept
1199 89069 : : Operand(Globals::Init, u0, baseId, indexId, uint32_t(offset)) {}
1200 : //! \endcond
1201 :
1202 : //! Creates a completely uninitialized `BaseMem` operand.
1203 : inline explicit BaseMem(Globals::NoInit_) noexcept
1204 : : Operand(Globals::NoInit) {}
1205 :
1206 : //! Resets the memory operand - after the reset the memory points to [0].
1207 : inline void reset() noexcept {
1208 0 : _signature = Signature::fromOpType(OperandType::kMem);
1209 0 : _baseId = 0;
1210 0 : _data[0] = 0;
1211 0 : _data[1] = 0;
1212 : }
1213 :
1214 : //! \}
1215 :
1216 : //! \name Overloaded Operators
1217 : //! \{
1218 :
1219 0 : inline BaseMem& operator=(const BaseMem& other) noexcept { copyFrom(other); return *this; }
1220 :
1221 : //! \}
1222 :
1223 : //! \name Accessors
1224 : //! \{
1225 :
1226 : //! Clones the memory operand.
1227 : inline constexpr BaseMem clone() const noexcept { return BaseMem(*this); }
1228 :
1229 : //! Creates a new copy of this memory operand adjusted by `off`.
1230 : inline BaseMem cloneAdjusted(int64_t off) const noexcept {
1231 : BaseMem result(*this);
1232 0 : result.addOffset(off);
1233 : return result;
1234 : }
1235 :
1236 : //! Tests whether this memory operand is a register home (only used by \ref asmjit_compiler)
1237 : inline constexpr bool isRegHome() const noexcept { return _signature.hasField<Signature::kMemRegHomeFlag>(); }
1238 : //! Mark this memory operand as register home (only used by \ref asmjit_compiler).
1239 : inline void setRegHome() noexcept { _signature |= Signature::kMemRegHomeFlag; }
1240 : //! Marks this operand to not be a register home (only used by \ref asmjit_compiler).
1241 : inline void clearRegHome() noexcept { _signature &= ~Signature::kMemRegHomeFlag; }
1242 :
1243 : //! Tests whether the memory operand has a BASE register or label specified.
1244 : inline constexpr bool hasBase() const noexcept {
1245 : return (_signature & Signature::kMemBaseTypeMask) != 0;
1246 : }
1247 :
1248 : //! Tests whether the memory operand has an INDEX register specified.
1249 : inline constexpr bool hasIndex() const noexcept {
1250 : return (_signature & Signature::kMemIndexTypeMask) != 0;
1251 : }
1252 :
1253 : //! Tests whether the memory operand has BASE or INDEX register.
1254 : inline constexpr bool hasBaseOrIndex() const noexcept {
1255 : return (_signature & Signature::kMemBaseIndexMask) != 0;
1256 : }
1257 :
1258 : //! Tests whether the memory operand has BASE and INDEX register.
1259 : inline constexpr bool hasBaseAndIndex() const noexcept {
1260 : return (_signature & Signature::kMemBaseTypeMask) != 0 && (_signature & Signature::kMemIndexTypeMask) != 0;
1261 : }
1262 :
1263 : //! Tests whether the BASE operand is a label.
1264 : inline constexpr bool hasBaseLabel() const noexcept {
1265 : return _signature.subset(Signature::kMemBaseTypeMask) == Signature::fromMemBaseType(RegType::kLabelTag);
1266 : }
1267 :
1268 : //! Tests whether the BASE operand is a register (registers start after `RegType::kLabelTag`).
1269 : inline constexpr bool hasBaseReg() const noexcept {
1270 : return _signature.subset(Signature::kMemBaseTypeMask).bits() > Signature::fromMemBaseType(RegType::kLabelTag).bits();
1271 : }
1272 :
1273 : //! Tests whether the INDEX operand is a register (registers start after `RegType::kLabelTag`).
1274 : inline constexpr bool hasIndexReg() const noexcept {
1275 : return _signature.subset(Signature::kMemIndexTypeMask).bits() > Signature::fromMemIndexType(RegType::kLabelTag).bits();
1276 : }
1277 :
1278 : //! Returns the type of the BASE register (0 if this memory operand doesn't use the BASE register).
1279 : //!
1280 : //! \note If the returned type is one (a value never associated to a register type) the BASE is not register, but it
1281 : //! is a label. One equals to `kLabelTag`. You should always check `hasBaseLabel()` before using `baseId()` result.
1282 : inline constexpr RegType baseType() const noexcept { return _signature.memBaseType(); }
1283 :
1284 : //! Returns the type of an INDEX register (0 if this memory operand doesn't
1285 : //! use the INDEX register).
1286 : inline constexpr RegType indexType() const noexcept { return _signature.memIndexType(); }
1287 :
1288 : //! This is used internally for BASE+INDEX validation.
1289 : inline constexpr uint32_t baseAndIndexTypes() const noexcept { return _signature.getField<Signature::kMemBaseIndexMask>(); }
1290 :
1291 : //! Returns both BASE (4:0 bits) and INDEX (9:5 bits) types combined into a single value.
1292 : //!
1293 : //! \remarks Returns id of the BASE register or label (if the BASE was specified as label).
1294 284190 : inline constexpr uint32_t baseId() const noexcept { return _baseId; }
1295 :
1296 : //! Returns the id of the INDEX register.
1297 20 : inline constexpr uint32_t indexId() const noexcept { return _data[kDataMemIndexId]; }
1298 :
1299 : //! Sets the id of the BASE register (without modifying its type).
1300 0 : inline void setBaseId(uint32_t id) noexcept { _baseId = id; }
1301 : //! Sets the id of the INDEX register (without modifying its type).
1302 : inline void setIndexId(uint32_t id) noexcept { _data[kDataMemIndexId] = id; }
1303 :
1304 : //! Sets the base register to type and id of the given `base` operand.
1305 : inline void setBase(const BaseReg& base) noexcept { return _setBase(base.type(), base.id()); }
1306 : //! Sets the index register to type and id of the given `index` operand.
1307 : inline void setIndex(const BaseReg& index) noexcept { return _setIndex(index.type(), index.id()); }
1308 :
1309 : //! \cond INTERNAL
1310 : inline void _setBase(RegType type, uint32_t id) noexcept {
1311 : _signature.setField<Signature::kMemBaseTypeMask>(uint32_t(type));
1312 71131 : _baseId = id;
1313 : }
1314 :
1315 : inline void _setIndex(RegType type, uint32_t id) noexcept {
1316 : _signature.setField<Signature::kMemIndexTypeMask>(uint32_t(type));
1317 : _data[kDataMemIndexId] = id;
1318 : }
1319 : //! \endcond
1320 :
1321 : //! Resets the memory operand's BASE register or label.
1322 : inline void resetBase() noexcept { _setBase(RegType::kNone, 0); }
1323 : //! Resets the memory operand's INDEX register.
1324 : inline void resetIndex() noexcept { _setIndex(RegType::kNone, 0); }
1325 :
1326 : //! Sets the memory operand size (in bytes).
1327 96852 : inline void setSize(uint32_t size) noexcept { _signature.setField<Signature::kSizeMask>(size); }
1328 :
1329 : //! Tests whether the memory operand has a 64-bit offset or absolute address.
1330 : //!
1331 : //! If this is true then `hasBase()` must always report false.
1332 0 : inline constexpr bool isOffset64Bit() const noexcept { return baseType() == RegType::kNone; }
1333 :
1334 : //! Tests whether the memory operand has a non-zero offset or absolute address.
1335 0 : inline constexpr bool hasOffset() const noexcept {
1336 0 : return (_data[kDataMemOffsetLo] | uint32_t(_baseId & Support::bitMaskFromBool<uint32_t>(isOffset64Bit()))) != 0;
1337 : }
1338 :
1339 : //! Returns either relative offset or absolute address as 64-bit integer.
1340 0 : inline constexpr int64_t offset() const noexcept {
1341 0 : return isOffset64Bit() ? int64_t(uint64_t(_data[kDataMemOffsetLo]) | (uint64_t(_baseId) << 32))
1342 0 : : int64_t(int32_t(_data[kDataMemOffsetLo])); // Sign extend 32-bit offset.
1343 : }
1344 :
1345 : //! Returns a 32-bit low part of a 64-bit offset or absolute address.
1346 142105 : inline constexpr int32_t offsetLo32() const noexcept { return int32_t(_data[kDataMemOffsetLo]); }
1347 : //! Returns a 32-but high part of a 64-bit offset or absolute address.
1348 : //!
1349 : //! \note This function is UNSAFE and returns garbage if `isOffset64Bit()`
1350 : //! returns false. Never use it blindly without checking it first.
1351 0 : inline constexpr int32_t offsetHi32() const noexcept { return int32_t(_baseId); }
1352 :
1353 : //! Sets a 64-bit offset or an absolute address to `offset`.
1354 : //!
1355 : //! \note This functions attempts to set both high and low parts of a 64-bit offset, however, if the operand has
1356 : //! a BASE register it will store only the low 32 bits of the offset / address as there is no way to store both
1357 : //! BASE and 64-bit offset, and there is currently no architecture that has such capability targeted by AsmJit.
1358 0 : inline void setOffset(int64_t offset) noexcept {
1359 0 : uint32_t lo = uint32_t(uint64_t(offset) & 0xFFFFFFFFu);
1360 0 : uint32_t hi = uint32_t(uint64_t(offset) >> 32);
1361 : uint32_t hiMsk = Support::bitMaskFromBool<uint32_t>(isOffset64Bit());
1362 :
1363 0 : _data[kDataMemOffsetLo] = lo;
1364 0 : _baseId = (hi & hiMsk) | (_baseId & ~hiMsk);
1365 0 : }
1366 : //! Sets a low 32-bit offset to `offset` (don't use without knowing how BaseMem works).
1367 0 : inline void setOffsetLo32(int32_t offset) noexcept { _data[kDataMemOffsetLo] = uint32_t(offset); }
1368 :
1369 : //! Adjusts the offset by `offset`.
1370 : //!
1371 : //! \note This is a fast function that doesn't use the HI 32-bits of a 64-bit offset. Use it only if you know that
1372 : //! there is a BASE register and the offset is only 32 bits anyway.
1373 :
1374 : //! Adjusts the memory operand offset by a `offset`.
1375 0 : inline void addOffset(int64_t offset) noexcept {
1376 0 : if (isOffset64Bit()) {
1377 0 : int64_t result = offset + int64_t(uint64_t(_data[kDataMemOffsetLo]) | (uint64_t(_baseId) << 32));
1378 0 : _data[kDataMemOffsetLo] = uint32_t(uint64_t(result) & 0xFFFFFFFFu);
1379 0 : _baseId = uint32_t(uint64_t(result) >> 32);
1380 : }
1381 : else {
1382 0 : _data[kDataMemOffsetLo] += uint32_t(uint64_t(offset) & 0xFFFFFFFFu);
1383 : }
1384 0 : }
1385 :
1386 : //! Adds `offset` to a low 32-bit offset part (don't use without knowing how BaseMem works).
1387 71131 : inline void addOffsetLo32(int32_t offset) noexcept { _data[kDataMemOffsetLo] += uint32_t(offset); }
1388 :
1389 : //! Resets the memory offset to zero.
1390 : inline void resetOffset() noexcept { setOffset(0); }
1391 :
1392 : //! Resets the lo part of the memory offset to zero (don't use without knowing how BaseMem works).
1393 : inline void resetOffsetLo32() noexcept { setOffsetLo32(0); }
1394 :
1395 : //! \}
1396 : };
1397 :
1398 : //! Type of the an immediate value.
1399 : enum class ImmType : uint32_t {
1400 : //! Immediate is integer.
1401 : kInt = 0,
1402 : //! Immediate is a floating point stored as double-precision.
1403 : kDouble = 1
1404 : };
1405 :
1406 : //! Immediate operands are encoded with instruction data.
1407 : class Imm : public Operand {
1408 : public:
1409 : //! \cond INTERNAL
1410 : template<typename T>
1411 : struct IsConstexprConstructibleAsImmType
1412 : : public std::integral_constant<bool, std::is_enum<T>::value ||
1413 : std::is_pointer<T>::value ||
1414 : std::is_integral<T>::value ||
1415 : std::is_function<T>::value> {};
1416 :
1417 : template<typename T>
1418 : struct IsConvertibleToImmType
1419 : : public std::integral_constant<bool, IsConstexprConstructibleAsImmType<T>::value ||
1420 : std::is_floating_point<T>::value> {};
1421 : //! \endcond
1422 :
1423 : //! \name Construction & Destruction
1424 : //! \{
1425 :
1426 : //! Creates a new immediate value (initial value is 0).
1427 : inline constexpr Imm() noexcept
1428 : : Operand(Globals::Init, Signature::fromOpType(OperandType::kImm), 0, 0, 0) {}
1429 :
1430 : //! Creates a new immediate value from `other`.
1431 : inline constexpr Imm(const Imm& other) noexcept
1432 188 : : Operand(other) {}
1433 :
1434 : //! Creates a new immediate value from ARM/AArch64 specific `shift`.
1435 : inline constexpr Imm(const arm::Shift& shift) noexcept
1436 : : Operand(Globals::Init,
1437 : Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(uint32_t(shift.op())),
1438 : 0,
1439 : Support::unpackU32At0(shift.value()),
1440 : Support::unpackU32At1(shift.value())) {}
1441 :
1442 : //! Creates a new signed immediate value, assigning the value to `val` and an architecture-specific predicate
1443 : //! to `predicate`.
1444 : //!
1445 : //! \note Predicate is currently only used by ARM architectures.
1446 : template<typename T, typename = typename std::enable_if<IsConstexprConstructibleAsImmType<typename std::decay<T>::type>::value>::type>
1447 : inline constexpr Imm(const T& val, const uint32_t predicate = 0) noexcept
1448 : : Operand(Globals::Init,
1449 : Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(predicate),
1450 : 0,
1451 : Support::unpackU32At0(int64_t(val)),
1452 88142 : Support::unpackU32At1(int64_t(val))) {}
1453 :
1454 : inline Imm(const float& val, const uint32_t predicate = 0) noexcept
1455 : : Operand(Globals::Init,
1456 : Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(predicate),
1457 : 0,
1458 : 0,
1459 : 0) { setValue(val); }
1460 :
1461 : inline Imm(const double& val, const uint32_t predicate = 0) noexcept
1462 : : Operand(Globals::Init,
1463 : Signature::fromOpType(OperandType::kImm) | Signature::fromPredicate(predicate),
1464 : 0,
1465 : 0,
1466 : 0) { setValue(val); }
1467 :
1468 : inline explicit Imm(Globals::NoInit_) noexcept
1469 : : Operand(Globals::NoInit) {}
1470 :
1471 : //! \}
1472 :
1473 : //! \name Overloaded Operators
1474 : //! \{
1475 :
1476 : //! Assigns the value of the `other` operand to this immediate.
1477 0 : inline Imm& operator=(const Imm& other) noexcept { copyFrom(other); return *this; }
1478 :
1479 : //! \}
1480 :
1481 : //! \name Accessors
1482 : //! \{
1483 :
1484 : //! Returns immediate type.
1485 : inline constexpr ImmType type() const noexcept { return (ImmType)_signature.getField<Signature::kImmTypeMask>(); }
1486 : //! Sets the immediate type to `type`.
1487 : inline void setType(ImmType type) noexcept { _signature.setField<Signature::kImmTypeMask>(uint32_t(type)); }
1488 : //! Resets immediate type to \ref ImmType::kInt.
1489 : inline void resetType() noexcept { setType(ImmType::kInt); }
1490 :
1491 : //! Returns operation predicate of the immediate.
1492 : //!
1493 : //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp
1494 : //! of the immediate.
1495 : inline constexpr uint32_t predicate() const noexcept { return _signature.getField<Signature::kPredicateMask>(); }
1496 :
1497 : //! Sets operation predicate of the immediate to `predicate`.
1498 : //!
1499 : //! The meaning depends on architecture, for example on ARM hardware this describes \ref arm::ShiftOp
1500 : //! of the immediate.
1501 : inline void setPredicate(uint32_t predicate) noexcept { _signature.setField<Signature::kPredicateMask>(predicate); }
1502 :
1503 : //! Resets the shift operation type of the immediate to the default value (no operation).
1504 : inline void resetPredicate() noexcept { _signature.setField<Signature::kPredicateMask>(0); }
1505 :
1506 : //! Returns the immediate value as `int64_t`, which is the internal format Imm uses.
1507 : inline constexpr int64_t value() const noexcept {
1508 100192 : return int64_t((uint64_t(_data[kDataImmValueHi]) << 32) | _data[kDataImmValueLo]);
1509 : }
1510 :
1511 : //! Tests whether this immediate value is integer of any size.
1512 : inline constexpr uint32_t isInt() const noexcept { return type() == ImmType::kInt; }
1513 : //! Tests whether this immediate value is a double precision floating point value.
1514 : inline constexpr uint32_t isDouble() const noexcept { return type() == ImmType::kDouble; }
1515 :
1516 : //! Tests whether the immediate can be casted to 8-bit signed integer.
1517 : inline constexpr bool isInt8() const noexcept { return type() == ImmType::kInt && Support::isInt8(value()); }
1518 : //! Tests whether the immediate can be casted to 8-bit unsigned integer.
1519 : inline constexpr bool isUInt8() const noexcept { return type() == ImmType::kInt && Support::isUInt8(value()); }
1520 : //! Tests whether the immediate can be casted to 16-bit signed integer.
1521 : inline constexpr bool isInt16() const noexcept { return type() == ImmType::kInt && Support::isInt16(value()); }
1522 : //! Tests whether the immediate can be casted to 16-bit unsigned integer.
1523 : inline constexpr bool isUInt16() const noexcept { return type() == ImmType::kInt && Support::isUInt16(value()); }
1524 : //! Tests whether the immediate can be casted to 32-bit signed integer.
1525 0 : inline constexpr bool isInt32() const noexcept { return type() == ImmType::kInt && Support::isInt32(value()); }
1526 : //! Tests whether the immediate can be casted to 32-bit unsigned integer.
1527 188 : inline constexpr bool isUInt32() const noexcept { return type() == ImmType::kInt && _data[kDataImmValueHi] == 0; }
1528 :
1529 : //! Returns the immediate value casted to `T`.
1530 : //!
1531 : //! The value is masked before it's casted to `T` so the returned value is simply the representation of `T`
1532 : //! considering the original value's lowest bits.
1533 : template<typename T>
1534 : inline T valueAs() const noexcept { return Support::immediateToT<T>(value()); }
1535 :
1536 : //! Returns low 32-bit signed integer.
1537 : inline constexpr int32_t int32Lo() const noexcept { return int32_t(_data[kDataImmValueLo]); }
1538 : //! Returns high 32-bit signed integer.
1539 : inline constexpr int32_t int32Hi() const noexcept { return int32_t(_data[kDataImmValueHi]); }
1540 : //! Returns low 32-bit signed integer.
1541 : inline constexpr uint32_t uint32Lo() const noexcept { return _data[kDataImmValueLo]; }
1542 : //! Returns high 32-bit signed integer.
1543 0 : inline constexpr uint32_t uint32Hi() const noexcept { return _data[kDataImmValueHi]; }
1544 :
1545 : //! Sets immediate value to `val`, the value is casted to a signed 64-bit integer.
1546 : template<typename T>
1547 : inline void setValue(const T& val) noexcept {
1548 : _setValueInternal(Support::immediateFromT(val), std::is_floating_point<T>::value ? ImmType::kDouble : ImmType::kInt);
1549 : }
1550 :
1551 : inline void _setValueInternal(int64_t val, ImmType type) noexcept {
1552 : setType(type);
1553 0 : _data[kDataImmValueHi] = uint32_t(uint64_t(val) >> 32);
1554 0 : _data[kDataImmValueLo] = uint32_t(uint64_t(val) & 0xFFFFFFFFu);
1555 : }
1556 :
1557 : //! \}
1558 :
1559 : //! \name Utilities
1560 : //! \{
1561 :
1562 : //! Clones the immediate operand.
1563 : inline constexpr Imm clone() const noexcept { return Imm(*this); }
1564 :
1565 0 : inline void signExtend8Bits() noexcept { setValue(int64_t(valueAs<int8_t>())); }
1566 0 : inline void signExtend16Bits() noexcept { setValue(int64_t(valueAs<int16_t>())); }
1567 0 : inline void signExtend32Bits() noexcept { setValue(int64_t(valueAs<int32_t>())); }
1568 :
1569 0 : inline void zeroExtend8Bits() noexcept { setValue(valueAs<uint8_t>()); }
1570 0 : inline void zeroExtend16Bits() noexcept { setValue(valueAs<uint16_t>()); }
1571 0 : inline void zeroExtend32Bits() noexcept { _data[kDataImmValueHi] = 0u; }
1572 :
1573 : //! \}
1574 : };
1575 :
1576 : //! Creates a new immediate operand.
1577 : template<typename T>
1578 : static inline constexpr Imm imm(const T& val) noexcept { return Imm(val); }
1579 :
1580 : //! \}
1581 :
1582 : namespace Globals {
1583 : //! \ingroup asmjit_assembler
1584 : //!
1585 : //! A default-constructed operand of `Operand_::kOpNone` type.
1586 : static constexpr const Operand none;
1587 : }
1588 :
1589 : //! \cond INTERNAL
1590 : namespace Support {
1591 :
1592 : template<typename T, bool kIsImm>
1593 : struct ForwardOpImpl {
1594 100442 : static inline const T& forward(const T& value) noexcept { return value; }
1595 : };
1596 :
1597 : template<typename T>
1598 : struct ForwardOpImpl<T, true> {
1599 0 : static inline Imm forward(const T& value) noexcept { return Imm(value); }
1600 : };
1601 :
1602 : //! Either forwards operand T or returns a new operand that wraps it if T is a type convertible to operand.
1603 : //! At the moment this is only used to convert integers, floats, and enumarations to \ref Imm operands.
1604 : template<typename T>
1605 : struct ForwardOp : public ForwardOpImpl<T, Imm::IsConvertibleToImmType<typename std::decay<T>::type>::value> {};
1606 :
1607 : } // {Support}
1608 : //! \endcond
1609 :
1610 : ASMJIT_END_NAMESPACE
1611 :
1612 : #endif // ASMJIT_CORE_OPERAND_H_INCLUDED
1613 :
1614 : #endif // __PLUMED_HAS_ASMJIT
|