1 // AsmJit - Machine code generation for C++
2 //
3 //  * Official AsmJit Home Page: https://asmjit.com
4 //  * Official Github Repository: https://github.com/asmjit/asmjit
5 //
6 // Copyright (c) 2008-2020 The AsmJit Authors
7 //
8 // This software is provided 'as-is', without any express or implied
9 // warranty. In no event will the authors be held liable for any damages
10 // arising from the use of this software.
11 //
12 // Permission is granted to anyone to use this software for any purpose,
13 // including commercial applications, and to alter it and redistribute it
14 // freely, subject to the following restrictions:
15 //
16 // 1. The origin of this software must not be misrepresented; you must not
17 //    claim that you wrote the original software. If you use this software
18 //    in a product, an acknowledgment in the product documentation would be
19 //    appreciated but is not required.
20 // 2. Altered source versions must be plainly marked as such, and must not be
21 //    misrepresented as being the original software.
22 // 3. This notice may not be removed or altered from any source distribution.
23 
24 #ifndef ASMJIT_CORE_OPERAND_H_INCLUDED
25 #define ASMJIT_CORE_OPERAND_H_INCLUDED
26 
27 #include "../core/archcommons.h"
28 #include "../core/support.h"
29 
30 ASMJIT_BEGIN_NAMESPACE
31 
32 // ============================================================================
33 // [Macros]
34 // ============================================================================
35 
36 //! Adds a template specialization for `REG_TYPE` into the local `RegTraits`.
37 #define ASMJIT_DEFINE_REG_TRAITS(REG, REG_TYPE, GROUP, SIZE, COUNT, TYPE_ID)  \
38 template<>                                                                    \
39 struct RegTraits<REG_TYPE> {                                                  \
40   typedef REG RegT;                                                           \
41                                                                               \
42   static constexpr uint32_t kValid = 1;                                       \
43   static constexpr uint32_t kCount = COUNT;                                   \
44   static constexpr uint32_t kTypeId = TYPE_ID;                                \
45                                                                               \
46   static constexpr uint32_t kType = REG_TYPE;                                 \
47   static constexpr uint32_t kGroup = GROUP;                                   \
48   static constexpr uint32_t kSize = SIZE;                                     \
49                                                                               \
50   static constexpr uint32_t kSignature =                                      \
51     (Operand::kOpReg << Operand::kSignatureOpTypeShift  ) |                   \
52     (kType           << Operand::kSignatureRegTypeShift ) |                   \
53     (kGroup          << Operand::kSignatureRegGroupShift) |                   \
54     (kSize           << Operand::kSignatureSizeShift    ) ;                   \
55 }
56 
57 //! Adds constructors and member functions to a class that implements abstract
58 //! register. Abstract register is register that doesn't have type or signature
59 //! yet, it's a base class like `x86::Reg` or `arm::Reg`.
60 #define ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE)                                 \
61 public:                                                                       \
62   /*! Default constructor that only setups basics. */                         \
63   constexpr REG() noexcept                                                    \
64     : BASE(SignatureAndId(kSignature, kIdBad)) {}                             \
65                                                                               \
66   /*! Makes a copy of the `other` register operand. */                        \
67   constexpr REG(const REG& other) noexcept                                    \
68     : BASE(other) {}                                                          \
69                                                                               \
70   /*! Makes a copy of the `other` register having id set to `rId` */          \
71   constexpr REG(const BaseReg& other, uint32_t rId) noexcept                  \
72     : BASE(other, rId) {}                                                     \
73                                                                               \
74   /*! Creates a register based on `signature` and `rId`. */                   \
75   constexpr explicit REG(const SignatureAndId& sid) noexcept                  \
76     : BASE(sid) {}                                                            \
77                                                                               \
78   /*! Creates a completely uninitialized REG register operand (garbage). */   \
79   inline explicit REG(Globals::NoInit_) noexcept                              \
80     : BASE(Globals::NoInit) {}                                                \
81                                                                               \
82   /*! Creates a new register from register type and id. */                    \
83   static inline REG fromTypeAndId(uint32_t rType, uint32_t rId) noexcept {    \
84     return REG(SignatureAndId(signatureOf(rType), rId));                      \
85   }                                                                           \
86                                                                               \
87   /*! Creates a new register from register signature and id. */               \
88   static inline REG fromSignatureAndId(uint32_t rSgn, uint32_t rId) noexcept {\
89     return REG(SignatureAndId(rSgn, rId));                                    \
90   }                                                                           \
91                                                                               \
92   /*! Clones the register operand. */                                         \
93   constexpr REG clone() const noexcept { return REG(*this); }                 \
94                                                                               \
95   inline REG& operator=(const REG& other) noexcept = default;
96 
97 //! Adds constructors and member functions to a class that implements final
98 //! register. Final registers MUST HAVE a valid signature.
99 #define ASMJIT_DEFINE_FINAL_REG(REG, BASE, TRAITS)                            \
100 public:                                                                       \
101   static constexpr uint32_t kThisType  = TRAITS::kType;                       \
102   static constexpr uint32_t kThisGroup = TRAITS::kGroup;                      \
103   static constexpr uint32_t kThisSize  = TRAITS::kSize;                       \
104   static constexpr uint32_t kSignature = TRAITS::kSignature;                  \
105                                                                               \
106   ASMJIT_DEFINE_ABSTRACT_REG(REG, BASE)                                       \
107                                                                               \
108   /*! Creates a register operand having its id set to `rId`. */               \
109   constexpr explicit REG(uint32_t rId) noexcept                               \
110     : BASE(SignatureAndId(kSignature, rId)) {}
111 
112 //! \addtogroup asmjit_assembler
113 //! \{
114 
115 // ============================================================================
116 // [asmjit::Operand_]
117 // ============================================================================
118 
119 //! Constructor-less `Operand`.
120 //!
121 //! Contains no initialization code and can be used safely to define an array
122 //! of operands that won't be initialized. This is an `Operand` compatible
123 //! data structure designed to be statically initialized, static const, or to
124 //! be used by the user to define an array of operands without having them
125 //! default initialized.
126 //!
127 //! The key difference between `Operand` and `Operand_`:
128 //!
129 //! ```
130 //! Operand_ xArray[10]; // Not initialized, contains garbage.
131 //! Operand  yArray[10]; // All operands initialized to none.
132 //! ```
133 struct Operand_ {
134   //! Operand's signature that provides operand type and additional information.
135   uint32_t _signature;
136   //! Either base id as used by memory operand or any id as used by others.
137   uint32_t _baseId;
138 
139   //! Data specific to the operand type.
140   //!
141   //! The reason we don't use union is that we have `constexpr` constructors that
142   //! construct operands and other `constexpr` functions that return wither another
143   //! Operand or something else. These cannot generally work with unions so we also
144   //! cannot use `union` if we want to be standard compliant.
145   uint32_t _data[2];
146 
147   //! Indexes to `_data` array.
148   enum DataIndex : uint32_t {
149     kDataMemIndexId  = 0,
150     kDataMemOffsetLo = 1,
151 
152     kDataImmValueLo = ASMJIT_ARCH_LE ? 0 : 1,
153     kDataImmValueHi = ASMJIT_ARCH_LE ? 1 : 0
154   };
155 
156   //! Operand types that can be encoded in `Operand`.
157   enum OpType : uint32_t {
158     //! Not an operand or not initialized.
159     kOpNone = 0,
160     //! Operand is a register.
161     kOpReg = 1,
162     //! Operand is a memory.
163     kOpMem = 2,
164     //! Operand is an immediate value.
165     kOpImm = 3,
166     //! Operand is a label.
167     kOpLabel = 4
168   };
169   static_assert(kOpMem == kOpReg + 1, "asmjit::Operand requires `kOpMem` to be `kOpReg+1`.");
170 
171   //! Label tag.
172   enum LabelTag {
173     //! Label tag is used as a sub-type, forming a unique signature across all
174     //! operand types as 0x1 is never associated with any register type. This
175     //! means that a memory operand's BASE register can be constructed from
176     //! virtually any operand (register vs. label) by just assigning its type
177     //! (register type or label-tag) and operand id.
178     kLabelTag = 0x1
179   };
180 
181   // \cond INTERNAL
182   enum SignatureBits : uint32_t {
183     // Operand type (3 least significant bits).
184     // |........|........|........|.....XXX|
185     kSignatureOpTypeShift = 0,
186     kSignatureOpTypeMask = 0x07u << kSignatureOpTypeShift,
187 
188     // Register type (5 bits).
189     // |........|........|........|XXXXX...|
190     kSignatureRegTypeShift = 3,
191     kSignatureRegTypeMask = 0x1Fu << kSignatureRegTypeShift,
192 
193     // Register group (4 bits).
194     // |........|........|....XXXX|........|
195     kSignatureRegGroupShift = 8,
196     kSignatureRegGroupMask = 0x0Fu << kSignatureRegGroupShift,
197 
198     // Memory base type (5 bits).
199     // |........|........|........|XXXXX...|
200     kSignatureMemBaseTypeShift = 3,
201     kSignatureMemBaseTypeMask = 0x1Fu << kSignatureMemBaseTypeShift,
202 
203     // Memory index type (5 bits).
204     // |........|........|...XXXXX|........|
205     kSignatureMemIndexTypeShift = 8,
206     kSignatureMemIndexTypeMask = 0x1Fu << kSignatureMemIndexTypeShift,
207 
208     // Memory base+index combined (10 bits).
209     // |........|........|...XXXXX|XXXXX...|
210     kSignatureMemBaseIndexShift = 3,
211     kSignatureMemBaseIndexMask = 0x3FFu << kSignatureMemBaseIndexShift,
212 
213     // This memory operand represents a home-slot or stack (Compiler) (1 bit).
214     // |........|........|..X.....|........|
215     kSignatureMemRegHomeShift = 13,
216     kSignatureMemRegHomeFlag = 0x01u << kSignatureMemRegHomeShift,
217 
218     // Immediate type (1 bit).
219     // |........|........|........|....X...|
220     kSignatureImmTypeShift = 4,
221     kSignatureImmTypeMask = 0x01u << kSignatureImmTypeShift,
222 
223     // Predicate used by either registers or immediate values (4 bits).
224     // |........|XXXX....|........|........|
225     kSignaturePredicateShift = 20,
226     kSignaturePredicateMask = 0x0Fu << kSignaturePredicateShift,
227 
228     // Operand size (8 most significant bits).
229     // |XXXXXXXX|........|........|........|
230     kSignatureSizeShift = 24,
231     kSignatureSizeMask = 0xFFu << kSignatureSizeShift
232   };
233   //! \endcond
234 
235   //! Constants useful for VirtId <-> Index translation.
236   enum VirtIdConstants : uint32_t {
237     //! Minimum valid packed-id.
238     kVirtIdMin = 256,
239     //! Maximum valid packed-id, excludes Globals::kInvalidId.
240     kVirtIdMax = Globals::kInvalidId - 1,
241     //! Count of valid packed-ids.
242     kVirtIdCount = uint32_t(kVirtIdMax - kVirtIdMin + 1)
243   };
244 
245   //! Tests whether the given `id` is a valid virtual register id. Since AsmJit
246   //! supports both physical and virtual registers it must be able to distinguish
247   //! between these two. The idea is that physical registers are always limited
248   //! in size, so virtual identifiers start from `kVirtIdMin` and end at `kVirtIdMax`.
isVirtIdOperand_249   static ASMJIT_INLINE bool isVirtId(uint32_t id) noexcept { return id - kVirtIdMin < uint32_t(kVirtIdCount); }
250   //! Converts a real-id into a packed-id that can be stored in Operand.
indexToVirtIdOperand_251   static ASMJIT_INLINE uint32_t indexToVirtId(uint32_t id) noexcept { return id + kVirtIdMin; }
252   //! Converts a packed-id back to real-id.
virtIdToIndexOperand_253   static ASMJIT_INLINE uint32_t virtIdToIndex(uint32_t id) noexcept { return id - kVirtIdMin; }
254 
255   //! \name Construction & Destruction
256   //! \{
257 
258   //! \cond INTERNAL
259   //! Initializes a `BaseReg` operand from `signature` and register `id`.
_initRegOperand_260   inline void _initReg(uint32_t signature, uint32_t id) noexcept {
261     _signature = signature;
262     _baseId = id;
263     _data[0] = 0;
264     _data[1] = 0;
265   }
266   //! \endcond
267 
268   //! Initializes the operand from `other` operand (used by operator overloads).
copyFromOperand_269   inline void copyFrom(const Operand_& other) noexcept { memcpy(this, &other, sizeof(Operand_)); }
270 
271   //! Resets the `Operand` to none.
272   //!
273   //! None operand is defined the following way:
274   //!   - Its signature is zero (kOpNone, and the rest zero as well).
275   //!   - Its id is `0`.
276   //!   - The reserved8_4 field is set to `0`.
277   //!   - The reserved12_4 field is set to zero.
278   //!
279   //! In other words, reset operands have all members set to zero. Reset operand
280   //! must match the Operand state right after its construction. Alternatively,
281   //! if you have an array of operands, you can simply use `memset()`.
282   //!
283   //! ```
284   //! using namespace asmjit;
285   //!
286   //! Operand a;
287   //! Operand b;
288   //! assert(a == b);
289   //!
290   //! b = x86::eax;
291   //! assert(a != b);
292   //!
293   //! b.reset();
294   //! assert(a == b);
295   //!
296   //! memset(&b, 0, sizeof(Operand));
297   //! assert(a == b);
298   //! ```
resetOperand_299   inline void reset() noexcept {
300     _signature = 0;
301     _baseId = 0;
302     _data[0] = 0;
303     _data[1] = 0;
304   }
305 
306   //! \}
307 
308   //! \name Operator Overloads
309   //! \{
310 
311   //! Tests whether this operand is the same as `other`.
312   constexpr bool operator==(const Operand_& other) const noexcept { return  equals(other); }
313   //! Tests whether this operand is not the same as `other`.
314   constexpr bool operator!=(const Operand_& other) const noexcept { return !equals(other); }
315 
316   //! \}
317 
318   //! \name Cast
319   //! \{
320 
321   //! Casts this operand to `T` type.
322   template<typename T>
asOperand_323   inline T& as() noexcept { return static_cast<T&>(*this); }
324 
325   //! Casts this operand to `T` type (const).
326   template<typename T>
asOperand_327   inline const T& as() const noexcept { return static_cast<const T&>(*this); }
328 
329   //! \}
330 
331   //! \name Accessors
332   //! \{
333 
334   //! Tests whether the operand's signature matches the given signature `sign`.
hasSignatureOperand_335   constexpr bool hasSignature(uint32_t signature) const noexcept { return _signature == signature; }
336   //! Tests whether the operand's signature matches the signature of the `other` operand.
hasSignatureOperand_337   constexpr bool hasSignature(const Operand_& other) const noexcept { return _signature == other.signature(); }
338 
339   //! Returns operand signature as unsigned 32-bit integer.
340   //!
341   //! Signature is first 4 bytes of the operand data. It's used mostly for
342   //! operand checking as it's much faster to check 4 bytes at once than having
343   //! to check these bytes individually.
signatureOperand_344   constexpr uint32_t signature() const noexcept { return _signature; }
345 
346   //! Sets the operand signature, see `signature()`.
347   //!
348   //! \note Improper use of `setSignature()` can lead to hard-to-debug errors.
setSignatureOperand_349   inline void setSignature(uint32_t signature) noexcept { _signature = signature; }
350 
351   //! \cond INTERNAL
352   template<uint32_t mask>
_hasSignaturePartOperand_353   constexpr bool _hasSignaturePart() const noexcept {
354     return (_signature & mask) != 0;
355   }
356 
357   template<uint32_t mask>
_hasSignaturePartOperand_358   constexpr bool _hasSignaturePart(uint32_t signature) const noexcept {
359     return (_signature & mask) == signature;
360   }
361 
362   template<uint32_t mask>
_getSignaturePartOperand_363   constexpr uint32_t _getSignaturePart() const noexcept {
364     return (_signature >> Support::constCtz(mask)) & (mask >> Support::constCtz(mask));
365   }
366 
367   template<uint32_t mask>
_setSignaturePartOperand_368   inline void _setSignaturePart(uint32_t value) noexcept {
369     ASMJIT_ASSERT((value & ~(mask >> Support::constCtz(mask))) == 0);
370     _signature = (_signature & ~mask) | (value << Support::constCtz(mask));
371   }
372   //! \endcond
373 
374   //! Returns the type of the operand, see `OpType`.
opTypeOperand_375   constexpr uint32_t opType() const noexcept { return _getSignaturePart<kSignatureOpTypeMask>(); }
376   //! Tests whether the operand is none (`kOpNone`).
isNoneOperand_377   constexpr bool isNone() const noexcept { return _signature == 0; }
378   //! Tests whether the operand is a register (`kOpReg`).
isRegOperand_379   constexpr bool isReg() const noexcept { return opType() == kOpReg; }
380   //! Tests whether the operand is a memory location (`kOpMem`).
isMemOperand_381   constexpr bool isMem() const noexcept { return opType() == kOpMem; }
382   //! Tests whether the operand is an immediate (`kOpImm`).
isImmOperand_383   constexpr bool isImm() const noexcept { return opType() == kOpImm; }
384   //! Tests whether the operand is a label (`kOpLabel`).
isLabelOperand_385   constexpr bool isLabel() const noexcept { return opType() == kOpLabel; }
386 
387   //! Tests whether the operand is a physical register.
isPhysRegOperand_388   constexpr bool isPhysReg() const noexcept { return isReg() && _baseId < 0xFFu; }
389   //! Tests whether the operand is a virtual register.
isVirtRegOperand_390   constexpr bool isVirtReg() const noexcept { return isReg() && _baseId > 0xFFu; }
391 
392   //! Tests whether the operand specifies a size (i.e. the size is not zero).
hasSizeOperand_393   constexpr bool hasSize() const noexcept { return _hasSignaturePart<kSignatureSizeMask>(); }
394   //! Tests whether the size of the operand matches `size`.
hasSizeOperand_395   constexpr bool hasSize(uint32_t s) const noexcept { return size() == s; }
396 
397   //! Returns the size of the operand in bytes.
398   //!
399   //! The value returned depends on the operand type:
400   //!   * None  - Should always return zero size.
401   //!   * Reg   - Should always return the size of the register. If the register
402   //!             size depends on architecture (like `x86::CReg` and `x86::DReg`)
403   //!             the size returned should be the greatest possible (so it should
404   //!             return 64-bit size in such case).
405   //!   * Mem   - Size is optional and will be in most cases zero.
406   //!   * Imm   - Should always return zero size.
407   //!   * Label - Should always return zero size.
sizeOperand_408   constexpr uint32_t size() const noexcept { return _getSignaturePart<kSignatureSizeMask>(); }
409 
410   //! Returns the operand id.
411   //!
412   //! The value returned should be interpreted accordingly to the operand type:
413   //!   * None  - Should be `0`.
414   //!   * Reg   - Physical or virtual register id.
415   //!   * Mem   - Multiple meanings - BASE address (register or label id), or
416   //!             high value of a 64-bit absolute address.
417   //!   * Imm   - Should be `0`.
418   //!   * Label - Label id if it was created by using `newLabel()` or
419   //!             `Globals::kInvalidId` if the label is invalid or not
420   //!             initialized.
idOperand_421   constexpr uint32_t id() const noexcept { return _baseId; }
422 
423   //! Tests whether the operand is 100% equal to `other` operand.
424   //!
425   //! \note This basically performs a binary comparison, if aby bit is
426   //! different the operands are not equal.
equalsOperand_427   constexpr bool equals(const Operand_& other) const noexcept {
428     return (_signature == other._signature) &
429            (_baseId    == other._baseId   ) &
430            (_data[0]   == other._data[0]  ) &
431            (_data[1]   == other._data[1]  ) ;
432   }
433 
434 #ifndef ASMJIT_NO_DEPRECATED
435   ASMJIT_DEPRECATED("Use equals() instead")
isEqualOperand_436   constexpr bool isEqual(const Operand_& other) const noexcept { return equals(other); }
437 #endif //!ASMJIT_NO_DEPRECATED
438 
439   //! Tests whether the operand is a register matching `rType`.
isRegOperand_440   constexpr bool isReg(uint32_t rType) const noexcept {
441     return (_signature & (kSignatureOpTypeMask | kSignatureRegTypeMask)) ==
442            ((kOpReg << kSignatureOpTypeShift) | (rType << kSignatureRegTypeShift));
443   }
444 
445   //! Tests whether the operand is register and of `rType` and `rId`.
isRegOperand_446   constexpr bool isReg(uint32_t rType, uint32_t rId) const noexcept {
447     return isReg(rType) && id() == rId;
448   }
449 
450   //! Tests whether the operand is a register or memory.
isRegOrMemOperand_451   constexpr bool isRegOrMem() const noexcept {
452     return Support::isBetween<uint32_t>(opType(), kOpReg, kOpMem);
453   }
454 
455   //! \}
456 };
457 
458 // ============================================================================
459 // [asmjit::Operand]
460 // ============================================================================
461 
462 //! Operand can contain register, memory location, immediate, or label.
463 class Operand : public Operand_ {
464 public:
465   //! \name Construction & Destruction
466   //! \{
467 
468   //! Creates `kOpNone` operand having all members initialized to zero.
Operand()469   constexpr Operand() noexcept
470     : Operand_{ kOpNone, 0u, { 0u, 0u }} {}
471 
472   //! Creates a cloned `other` operand.
473   constexpr Operand(const Operand& other) noexcept = default;
474 
475   //! Creates a cloned `other` operand.
Operand(const Operand_ & other)476   constexpr explicit Operand(const Operand_& other)
477     : Operand_(other) {}
478 
479   //! Creates an operand initialized to raw `[u0, u1, u2, u3]` values.
Operand(Globals::Init_,uint32_t u0,uint32_t u1,uint32_t u2,uint32_t u3)480   constexpr Operand(Globals::Init_, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept
481     : Operand_{ u0, u1, { u2, u3 }} {}
482 
483   //! Creates an uninitialized operand (dangerous).
Operand(Globals::NoInit_)484   inline explicit Operand(Globals::NoInit_) noexcept {}
485 
486   //! \}
487 
488   //! \name Operator Overloads
489   //! \{
490 
491   inline Operand& operator=(const Operand& other) noexcept = default;
492   inline Operand& operator=(const Operand_& other) noexcept { return operator=(static_cast<const Operand&>(other)); }
493 
494   //! \}
495 
496   //! \name Utilities
497   //! \{
498 
499   //! Clones this operand and returns its copy.
clone()500   constexpr Operand clone() const noexcept { return Operand(*this); }
501 
502   //! \}
503 };
504 
505 static_assert(sizeof(Operand) == 16, "asmjit::Operand must be exactly 16 bytes long");
506 
507 // ============================================================================
508 // [asmjit::Label]
509 // ============================================================================
510 
511 //! Label (jump target or data location).
512 //!
513 //! Label represents a location in code typically used as a jump target, but
514 //! may be also a reference to some data or a static variable. Label has to be
515 //! explicitly created by BaseEmitter.
516 //!
517 //! Example of using labels:
518 //!
519 //! ```
520 //! // Create some emitter (for example x86::Assembler).
521 //! x86::Assembler a;
522 //!
523 //! // Create Label instance.
524 //! Label L1 = a.newLabel();
525 //!
526 //! // ... your code ...
527 //!
528 //! // Using label.
529 //! a.jump(L1);
530 //!
531 //! // ... your code ...
532 //!
533 //! // Bind label to the current position, see `BaseEmitter::bind()`.
534 //! a.bind(L1);
535 //! ```
536 class Label : public Operand {
537 public:
538   //! Type of the Label.
539   enum LabelType : uint32_t {
540     //! Anonymous (unnamed) label.
541     kTypeAnonymous = 0,
542     //! Local label (always has parentId).
543     kTypeLocal = 1,
544     //! Global label (never has parentId).
545     kTypeGlobal = 2,
546     //! External label (references an external symbol).
547     kTypeExternal = 3,
548     //! Number of label types.
549     kTypeCount = 4
550   };
551 
552   //! \name Construction & Destruction
553   //! \{
554 
555   //! Creates a label operand without ID (you must set the ID to make it valid).
Label()556   constexpr Label() noexcept
557     : Operand(Globals::Init, kOpLabel, Globals::kInvalidId, 0, 0) {}
558 
559   //! Creates a cloned label operand of `other`.
Label(const Label & other)560   constexpr Label(const Label& other) noexcept
561     : Operand(other) {}
562 
563   //! Creates a label operand of the given `id`.
Label(uint32_t id)564   constexpr explicit Label(uint32_t id) noexcept
565     : Operand(Globals::Init, kOpLabel, id, 0, 0) {}
566 
Label(Globals::NoInit_)567   inline explicit Label(Globals::NoInit_) noexcept
568     : Operand(Globals::NoInit) {}
569 
570   //! Resets the label, will reset all properties and set its ID to `Globals::kInvalidId`.
reset()571   inline void reset() noexcept {
572     _signature = kOpLabel;
573     _baseId = Globals::kInvalidId;
574     _data[0] = 0;
575     _data[1] = 0;
576   }
577 
578   //! \}
579 
580   //! \name Overloaded Operators
581   //! \{
582 
583   inline Label& operator=(const Label& other) noexcept = default;
584 
585   //! \}
586 
587   //! \name Accessors
588   //! \{
589 
590   //! Tests whether the label was created by CodeHolder and/or an attached emitter.
isValid()591   constexpr bool isValid() const noexcept { return _baseId != Globals::kInvalidId; }
592   //! Sets the label `id`.
setId(uint32_t id)593   inline void setId(uint32_t id) noexcept { _baseId = id; }
594 
595   //! \}
596 };
597 
598 // ============================================================================
599 // [asmjit::BaseRegTraits]
600 // ============================================================================
601 
602 //! \cond INTERNAL
603 //! Default register traits.
604 struct BaseRegTraits {
605   //! RegType is not valid by default.
606   static constexpr uint32_t kValid = 0;
607   //! Count of registers (0 if none).
608   static constexpr uint32_t kCount = 0;
609   //! Everything is void by default.
610   static constexpr uint32_t kTypeId = 0;
611 
612   //! Zero type by default.
613   static constexpr uint32_t kType = 0;
614   //! Zero group by default.
615   static constexpr uint32_t kGroup = 0;
616   //! No size by default.
617   static constexpr uint32_t kSize = 0;
618 
619   //! Empty signature by default (not even having operand type set to register).
620   static constexpr uint32_t kSignature = 0;
621 };
622 //! \endcond
623 
624 // ============================================================================
625 // [asmjit::BaseReg]
626 // ============================================================================
627 
628 //! Structure that allows to extract a register information based on the signature.
629 //!
630 //! This information is compatible with operand's signature (32-bit integer)
631 //! and `RegInfo` just provides easy way to access it.
632 struct RegInfo {
633   inline void reset(uint32_t signature = 0) noexcept { _signature = signature; }
setSignatureRegInfo634   inline void setSignature(uint32_t signature) noexcept { _signature = signature; }
635 
636   template<uint32_t mask>
_getSignaturePartRegInfo637   constexpr uint32_t _getSignaturePart() const noexcept {
638     return (_signature >> Support::constCtz(mask)) & (mask >> Support::constCtz(mask));
639   }
640 
isValidRegInfo641   constexpr bool isValid() const noexcept { return _signature != 0; }
signatureRegInfo642   constexpr uint32_t signature() const noexcept { return _signature; }
opTypeRegInfo643   constexpr uint32_t opType() const noexcept { return _getSignaturePart<Operand::kSignatureOpTypeMask>(); }
groupRegInfo644   constexpr uint32_t group() const noexcept { return _getSignaturePart<Operand::kSignatureRegGroupMask>(); }
typeRegInfo645   constexpr uint32_t type() const noexcept { return _getSignaturePart<Operand::kSignatureRegTypeMask>(); }
sizeRegInfo646   constexpr uint32_t size() const noexcept { return _getSignaturePart<Operand::kSignatureSizeMask>(); }
647 
648   uint32_t _signature;
649 };
650 
651 //! Physical or virtual register operand.
652 class BaseReg : public Operand {
653 public:
654   static constexpr uint32_t kBaseSignature =
655     kSignatureOpTypeMask   |
656     kSignatureRegTypeMask  |
657     kSignatureRegGroupMask |
658     kSignatureSizeMask     ;
659 
660   //! Architecture neutral register types.
661   //!
662   //! These must be reused by any platform that contains that types. All GP
663   //! and VEC registers are also allowed by design to be part of a BASE|INDEX
664   //! of a memory operand.
665   enum RegType : uint32_t {
666     //! No register - unused, invalid, multiple meanings.
667     kTypeNone = 0,
668 
669     // (1 is used as a LabelTag)
670 
671     //! 8-bit low general purpose register (X86).
672     kTypeGp8Lo = 2,
673     //! 8-bit high general purpose register (X86).
674     kTypeGp8Hi = 3,
675     //! 16-bit general purpose register (X86).
676     kTypeGp16 = 4,
677     //! 32-bit general purpose register (X86|ARM).
678     kTypeGp32 = 5,
679     //! 64-bit general purpose register (X86|ARM).
680     kTypeGp64 = 6,
681     //! 8-bit view of a vector register (ARM).
682     kTypeVec8 = 7,
683     //! 16-bit view of a vector register (ARM).
684     kTypeVec16 = 8,
685     //! 32-bit view of a vector register (ARM).
686     kTypeVec32 = 9,
687     //! 64-bit view of a vector register (ARM).
688     kTypeVec64 = 10,
689     //! 128-bit view of a vector register (X86|ARM).
690     kTypeVec128 = 11,
691     //! 256-bit view of a vector register (X86).
692     kTypeVec256 = 12,
693     //! 512-bit view of a vector register (X86).
694     kTypeVec512 = 13,
695     //! 1024-bit view of a vector register (future).
696     kTypeVec1024 = 14,
697     //! Other0 register, should match `kOther0` group.
698     kTypeOther0 = 15,
699     //! Other1 register, should match `kOther1` group.
700     kTypeOther1 = 16,
701     //! Universal id of IP/PC register (if separate).
702     kTypeIP = 17,
703     //! Start of platform dependent register types.
704     kTypeCustom = 18,
705     //! Maximum possible register type value.
706     kTypeMax = 31
707   };
708 
709   //! Register group (architecture neutral), and some limits.
710   enum RegGroup : uint32_t {
711     //! General purpose register group compatible with all backends.
712     kGroupGp = 0,
713     //! Vector register group compatible with all backends.
714     kGroupVec = 1,
715     //! Group that is architecture dependent.
716     kGroupOther0 = 2,
717     //! Group that is architecture dependent.
718     kGroupOther1 = 3,
719     //! Count of register groups used by physical and virtual registers.
720     kGroupVirt = 4,
721     //! Count of register groups used by physical registers only.
722     kGroupCount = 16
723   };
724 
725   enum Id : uint32_t {
726     //! None or any register (mostly internal).
727     kIdBad = 0xFFu
728   };
729 
730   //! A helper used by constructors.
731   struct SignatureAndId {
732     uint32_t _signature;
733     uint32_t _id;
734 
735     inline SignatureAndId() noexcept = default;
736     constexpr SignatureAndId(const SignatureAndId& other) noexcept = default;
737 
SignatureAndIdSignatureAndId738     constexpr explicit SignatureAndId(uint32_t signature, uint32_t id) noexcept
739       : _signature(signature),
740         _id(id) {}
741 
signatureSignatureAndId742     constexpr uint32_t signature() const noexcept { return _signature; }
idSignatureAndId743     constexpr uint32_t id() const noexcept { return _id; }
744   };
745 
746   static constexpr uint32_t kSignature = kOpReg;
747 
748   //! \name Construction & Destruction
749   //! \{
750 
751   //! Creates a dummy register operand.
BaseReg()752   constexpr BaseReg() noexcept
753     : Operand(Globals::Init, kSignature, kIdBad, 0, 0) {}
754 
755   //! Creates a new register operand which is the same as `other` .
BaseReg(const BaseReg & other)756   constexpr BaseReg(const BaseReg& other) noexcept
757     : Operand(other) {}
758 
759   //! Creates a new register operand compatible with `other`, but with a different `rId`.
BaseReg(const BaseReg & other,uint32_t rId)760   constexpr BaseReg(const BaseReg& other, uint32_t rId) noexcept
761     : Operand(Globals::Init, other._signature, rId, 0, 0) {}
762 
763   //! Creates a register initialized to `signature` and `rId`.
BaseReg(const SignatureAndId & sid)764   constexpr explicit BaseReg(const SignatureAndId& sid) noexcept
765     : Operand(Globals::Init, sid._signature, sid._id, 0, 0) {}
766 
BaseReg(Globals::NoInit_)767   inline explicit BaseReg(Globals::NoInit_) noexcept
768     : Operand(Globals::NoInit) {}
769 
770   /*! Creates a new register from register signature `rSgn` and id. */
fromSignatureAndId(uint32_t rSgn,uint32_t rId)771   static inline BaseReg fromSignatureAndId(uint32_t rSgn, uint32_t rId) noexcept {
772     return BaseReg(SignatureAndId(rSgn, rId));
773   }
774 
775   //! \}
776 
777   //! \name Overloaded Operators
778   //! \{
779 
780   inline BaseReg& operator=(const BaseReg& other) noexcept = default;
781 
782   //! \}
783 
784   //! \name Accessors
785   //! \{
786 
787   //! Returns base signature of the register associated with each register type.
788   //!
789   //! Base signature only contains the operand type, register type, register
790   //! group, and register size. It doesn't contain element type, predicate, or
791   //! other architecture-specific data. Base signature is a signature that is
792   //! provided by architecture-specific `RegTraits`, like \ref x86::RegTraits.
baseSignature()793   constexpr uint32_t baseSignature() const noexcept {
794     return _signature & (kBaseSignature);
795   }
796 
797   //! Tests whether the operand's base signature matches the given signature `sign`.
hasBaseSignature(uint32_t signature)798   constexpr bool hasBaseSignature(uint32_t signature) const noexcept { return baseSignature() == signature; }
799   //! Tests whether the operand's base signature matches the base signature of the `other` operand.
hasBaseSignature(const BaseReg & other)800   constexpr bool hasBaseSignature(const BaseReg& other) const noexcept { return baseSignature() == other.baseSignature(); }
801 
802   //! Tests whether this register is the same as `other`.
803   //!
804   //! This is just an optimization. Registers by default only use the first
805   //! 8 bytes of Operand data, so this method takes advantage of this knowledge
806   //! and only compares these 8 bytes. If both operands were created correctly
807   //! both \ref equals() and \ref isSame() should give the same answer, however,
808   //! if any of these two contains garbage or other metadata in the upper 8
809   //! bytes then \ref isSame() may return `true` in cases in which \ref equals()
810   //! returns false.
isSame(const BaseReg & other)811   constexpr bool isSame(const BaseReg& other) const noexcept {
812     return (_signature == other._signature) & (_baseId == other._baseId);
813   }
814 
815   //! Tests whether the register is valid (either virtual or physical).
isValid()816   constexpr bool isValid() const noexcept { return (_signature != 0) & (_baseId != kIdBad); }
817 
818   //! Tests whether this is a physical register.
isPhysReg()819   constexpr bool isPhysReg() const noexcept { return _baseId < kIdBad; }
820   //! Tests whether this is a virtual register.
isVirtReg()821   constexpr bool isVirtReg() const noexcept { return _baseId > kIdBad; }
822 
823   //! Tests whether the register type matches `type` - same as `isReg(type)`, provided for convenience.
isType(uint32_t type)824   constexpr bool isType(uint32_t type) const noexcept { return (_signature & kSignatureRegTypeMask) == (type << kSignatureRegTypeShift); }
825   //! Tests whether the register group matches `group`.
isGroup(uint32_t group)826   constexpr bool isGroup(uint32_t group) const noexcept { return (_signature & kSignatureRegGroupMask) == (group << kSignatureRegGroupShift); }
827 
828   //! Tests whether the register is a general purpose register (any size).
isGp()829   constexpr bool isGp() const noexcept { return isGroup(kGroupGp); }
830   //! Tests whether the register is a vector register.
isVec()831   constexpr bool isVec() const noexcept { return isGroup(kGroupVec); }
832 
833   using Operand_::isReg;
834 
835   //! Same as `isType()`, provided for convenience.
isReg(uint32_t rType)836   constexpr bool isReg(uint32_t rType) const noexcept { return isType(rType); }
837   //! Tests whether the register type matches `type` and register id matches `rId`.
isReg(uint32_t rType,uint32_t rId)838   constexpr bool isReg(uint32_t rType, uint32_t rId) const noexcept { return isType(rType) && id() == rId; }
839 
840   //! Returns the type of the register.
type()841   constexpr uint32_t type() const noexcept { return _getSignaturePart<kSignatureRegTypeMask>(); }
842   //! Returns the register group.
group()843   constexpr uint32_t group() const noexcept { return _getSignaturePart<kSignatureRegGroupMask>(); }
844 
845   //! Returns operation predicate of the register (ARM/AArch64).
846   //!
847   //! The meaning depends on architecture, for example on ARM hardware this
848   //! describes \ref arm::Predicate::ShiftOp of the register.
predicate()849   constexpr uint32_t predicate() const noexcept { return _getSignaturePart<kSignaturePredicateMask>(); }
850 
851   //! Sets operation predicate of the register to `predicate` (ARM/AArch64).
852   //!
853   //! The meaning depends on architecture, for example on ARM hardware this
854   //! describes \ref arm::Predicate::ShiftOp of the register.
setPredicate(uint32_t predicate)855   inline void setPredicate(uint32_t predicate) noexcept { _setSignaturePart<kSignaturePredicateMask>(predicate); }
856 
857   //! Resets shift operation type of the register to the default value (ARM/AArch64).
resetPredicate()858   inline void resetPredicate() noexcept { _setSignaturePart<kSignaturePredicateMask>(0); }
859 
860   //! Clones the register operand.
clone()861   constexpr BaseReg clone() const noexcept { return BaseReg(*this); }
862 
863   //! Casts this register to `RegT` by also changing its signature.
864   //!
865   //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors.
866   template<typename RegT>
cloneAs()867   constexpr RegT cloneAs() const noexcept { return RegT(RegT::kSignature, id()); }
868 
869   //! Casts this register to `other` by also changing its signature.
870   //!
871   //! \note Improper use of `cloneAs()` can lead to hard-to-debug errors.
872   template<typename RegT>
cloneAs(const RegT & other)873   constexpr RegT cloneAs(const RegT& other) const noexcept { return RegT(SignatureAndId(other.signature(), id())); }
874 
875   //! Sets the register id to `rId`.
setId(uint32_t rId)876   inline void setId(uint32_t rId) noexcept { _baseId = rId; }
877 
878   //! Sets a 32-bit operand signature based on traits of `RegT`.
879   template<typename RegT>
setSignatureT()880   inline void setSignatureT() noexcept { _signature = RegT::kSignature; }
881 
882   //! Sets the register `signature` and `rId`.
setSignatureAndId(uint32_t signature,uint32_t rId)883   inline void setSignatureAndId(uint32_t signature, uint32_t rId) noexcept {
884     _signature = signature;
885     _baseId = rId;
886   }
887 
888   //! \}
889 
890   //! \name Static Functions
891   //! \{
892 
893   //! Tests whether the `op` operand is a general purpose register.
isGp(const Operand_ & op)894   static inline bool isGp(const Operand_& op) noexcept {
895     // Check operand type and register group. Not interested in register type and size.
896     const uint32_t kSgn = (kOpReg   << kSignatureOpTypeShift  ) |
897                           (kGroupGp << kSignatureRegGroupShift) ;
898     return (op.signature() & (kSignatureOpTypeMask | kSignatureRegGroupMask)) == kSgn;
899   }
900 
901   //! Tests whether the `op` operand is a vector register.
isVec(const Operand_ & op)902   static inline bool isVec(const Operand_& op) noexcept {
903     // Check operand type and register group. Not interested in register type and size.
904     const uint32_t kSgn = (kOpReg    << kSignatureOpTypeShift  ) |
905                           (kGroupVec << kSignatureRegGroupShift) ;
906     return (op.signature() & (kSignatureOpTypeMask | kSignatureRegGroupMask)) == kSgn;
907   }
908 
909   //! Tests whether the `op` is a general purpose register of the given `rId`.
isGp(const Operand_ & op,uint32_t rId)910   static inline bool isGp(const Operand_& op, uint32_t rId) noexcept { return isGp(op) & (op.id() == rId); }
911   //! Tests whether the `op` is a vector register of the given `rId`.
isVec(const Operand_ & op,uint32_t rId)912   static inline bool isVec(const Operand_& op, uint32_t rId) noexcept { return isVec(op) & (op.id() == rId); }
913 
914   //! \}
915 };
916 
917 // ============================================================================
918 // [asmjit::RegOnly]
919 // ============================================================================
920 
921 //! RegOnly is 8-byte version of `BaseReg` that allows to store either register
922 //! or nothing.
923 //!
924 //! This class was designed to decrease the space consumed by each extra "operand"
925 //! in `BaseEmitter` and `InstNode` classes.
926 struct RegOnly {
927   //! Type of the operand, either `kOpNone` or `kOpReg`.
928   uint32_t _signature;
929   //! Physical or virtual register id.
930   uint32_t _id;
931 
932   //! \name Construction & Destruction
933   //! \{
934 
935   //! Initializes the `RegOnly` instance to hold register `signature` and `id`.
initRegOnly936   inline void init(uint32_t signature, uint32_t id) noexcept {
937     _signature = signature;
938     _id = id;
939   }
940 
initRegOnly941   inline void init(const BaseReg& reg) noexcept { init(reg.signature(), reg.id()); }
initRegOnly942   inline void init(const RegOnly& reg) noexcept { init(reg.signature(), reg.id()); }
943 
944   //! Resets the `RegOnly` members to zeros (none).
resetRegOnly945   inline void reset() noexcept { init(0, 0); }
946 
947   //! \}
948 
949   //! \name Accessors
950   //! \{
951 
952   //! Tests whether this ExtraReg is none (same as calling `Operand_::isNone()`).
isNoneRegOnly953   constexpr bool isNone() const noexcept { return _signature == 0; }
954   //! Tests whether the register is valid (either virtual or physical).
isRegRegOnly955   constexpr bool isReg() const noexcept { return _signature != 0; }
956 
957   //! Tests whether this is a physical register.
isPhysRegRegOnly958   constexpr bool isPhysReg() const noexcept { return _id < BaseReg::kIdBad; }
959   //! Tests whether this is a virtual register (used by `BaseCompiler`).
isVirtRegRegOnly960   constexpr bool isVirtReg() const noexcept { return _id > BaseReg::kIdBad; }
961 
962   //! Returns the register signature or 0 if no register is assigned.
signatureRegOnly963   constexpr uint32_t signature() const noexcept { return _signature; }
964   //! Returns the register id.
965   //!
966   //! \note Always check whether the register is assigned before using the
967   //! returned identifier as non-assigned `RegOnly` instance would return
968   //! zero id, which is still a valid register id.
idRegOnly969   constexpr uint32_t id() const noexcept { return _id; }
970 
971   //! Sets the register id.
setIdRegOnly972   inline void setId(uint32_t id) noexcept { _id = id; }
973 
974   //! \cond INTERNAL
975   //!
976   //! Extracts information from operand's signature.
977   template<uint32_t mask>
_getSignaturePartRegOnly978   constexpr uint32_t _getSignaturePart() const noexcept {
979     return (_signature >> Support::constCtz(mask)) & (mask >> Support::constCtz(mask));
980   }
981   //! \endcond
982 
983   //! Returns the type of the register.
typeRegOnly984   constexpr uint32_t type() const noexcept { return _getSignaturePart<Operand::kSignatureRegTypeMask>(); }
985   //! Returns the register group.
groupRegOnly986   constexpr uint32_t group() const noexcept { return _getSignaturePart<Operand::kSignatureRegGroupMask>(); }
987 
988   //! \}
989 
990   //! \name Utilities
991   //! \{
992 
993   //! Converts this ExtraReg to a real `RegT` operand.
994   template<typename RegT>
toRegRegOnly995   constexpr RegT toReg() const noexcept { return RegT(BaseReg::SignatureAndId(_signature, _id)); }
996 
997   //! \}
998 };
999 
1000 // ============================================================================
1001 // [asmjit::BaseMem]
1002 // ============================================================================
1003 
1004 //! Base class for all memory operands.
1005 //!
1006 //! \note It's tricky to pack all possible cases that define a memory operand
1007 //! into just 16 bytes. The `BaseMem` splits data into the following parts:
1008 //!
1009 //!   - BASE - Base register or label - requires 36 bits total. 4 bits are used
1010 //!     to encode the type of the BASE operand (label vs. register type) and the
1011 //!     remaining 32 bits define the BASE id, which can be a physical or virtual
1012 //!     register index. If BASE type is zero, which is never used as a register
1013 //!     type and label doesn't use it as well then BASE field contains a high
1014 //!     DWORD of a possible 64-bit absolute address, which is possible on X64.
1015 //!
1016 //!   - INDEX - Index register (or theoretically Label, which doesn't make sense).
1017 //!     Encoding is similar to BASE - it also requires 36 bits and splits the
1018 //!     encoding to INDEX type (4 bits defining the register type) and id (32-bits).
1019 //!
1020 //!   - OFFSET - A relative offset of the address. Basically if BASE is specified
1021 //!     the relative displacement adjusts BASE and an optional INDEX. if BASE is
1022 //!     not specified then the OFFSET should be considered as ABSOLUTE address (at
1023 //!     least on X86). In that case its low 32 bits are stored in DISPLACEMENT
1024 //!     field and the remaining high 32 bits are stored in BASE.
1025 //!
1026 //!   - OTHER - There is rest 8 bits that can be used for whatever purpose. For
1027 //!     example \ref x86::Mem operand uses these bits to store segment override
1028 //!     prefix and index shift (or scale).
1029 class BaseMem : public Operand {
1030 public:
1031   //! \cond INTERNAL
1032   //! Used internally to construct `BaseMem` operand from decomposed data.
1033   struct Decomposed {
1034     uint32_t baseType;
1035     uint32_t baseId;
1036     uint32_t indexType;
1037     uint32_t indexId;
1038     int32_t offset;
1039     uint32_t size;
1040     uint32_t flags;
1041   };
1042   //! \endcond
1043 
1044   //! \name Construction & Destruction
1045   //! \{
1046 
1047   //! Creates a default `BaseMem` operand, that points to [0].
BaseMem()1048   constexpr BaseMem() noexcept
1049     : Operand(Globals::Init, kOpMem, 0, 0, 0) {}
1050 
1051   //! Creates a `BaseMem` operand that is a clone of `other`.
BaseMem(const BaseMem & other)1052   constexpr BaseMem(const BaseMem& other) noexcept
1053     : Operand(other) {}
1054 
1055   //! Creates a `BaseMem` operand from `baseReg` and `offset`.
1056   //!
1057   //! \note This is an architecture independent constructor that can be used to
1058   //! create an architecture independent memory operand to be used in portable
1059   //! code that can handle multiple architectures.
1060   constexpr explicit BaseMem(const BaseReg& baseReg, int32_t offset = 0) noexcept
1061     : Operand(Globals::Init,
1062               kOpMem | (baseReg.type() << kSignatureMemBaseTypeShift),
1063               baseReg.id(),
1064               0,
1065               uint32_t(offset)) {}
1066 
1067   //! \cond INTERNAL
1068 
1069   //! Creates a `BaseMem` operand from 4 integers as used by `Operand_` struct.
BaseMem(Globals::Init_,uint32_t u0,uint32_t u1,uint32_t u2,uint32_t u3)1070   constexpr BaseMem(Globals::Init_, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept
1071     : Operand(Globals::Init, u0, u1, u2, u3) {}
1072 
BaseMem(const Decomposed & d)1073   constexpr BaseMem(const Decomposed& d) noexcept
1074     : Operand(Globals::Init,
1075               kOpMem | (d.baseType  << kSignatureMemBaseTypeShift )
1076                      | (d.indexType << kSignatureMemIndexTypeShift)
1077                      | (d.size      << kSignatureSizeShift        )
1078                      | d.flags,
1079               d.baseId,
1080               d.indexId,
1081               uint32_t(d.offset)) {}
1082 
1083   //! \endcond
1084 
1085   //! Creates a completely uninitialized `BaseMem` operand.
BaseMem(Globals::NoInit_)1086   inline explicit BaseMem(Globals::NoInit_) noexcept
1087     : Operand(Globals::NoInit) {}
1088 
1089   //! Resets the memory operand - after the reset the memory points to [0].
reset()1090   inline void reset() noexcept {
1091     _signature = kOpMem;
1092     _baseId = 0;
1093     _data[0] = 0;
1094     _data[1] = 0;
1095   }
1096 
1097   //! \}
1098 
1099   //! \name Overloaded Operators
1100   //! \{
1101 
1102   inline BaseMem& operator=(const BaseMem& other) noexcept { copyFrom(other); return *this; }
1103 
1104   //! \}
1105 
1106   //! \name Accessors
1107   //! \{
1108 
1109   //! Clones the memory operand.
clone()1110   constexpr BaseMem clone() const noexcept { return BaseMem(*this); }
1111 
1112   //! Creates a new copy of this memory operand adjusted by `off`.
cloneAdjusted(int64_t off)1113   inline BaseMem cloneAdjusted(int64_t off) const noexcept {
1114     BaseMem result(*this);
1115     result.addOffset(off);
1116     return result;
1117   }
1118 
1119   //! Tests whether this memory operand is a register home (only used by \ref asmjit_compiler)
isRegHome()1120   constexpr bool isRegHome() const noexcept { return _hasSignaturePart<kSignatureMemRegHomeFlag>(); }
1121   //! Mark this memory operand as register home (only used by \ref asmjit_compiler).
setRegHome()1122   inline void setRegHome() noexcept { _signature |= kSignatureMemRegHomeFlag; }
1123   //! Marks this operand to not be a register home (only used by \ref asmjit_compiler).
clearRegHome()1124   inline void clearRegHome() noexcept { _signature &= ~kSignatureMemRegHomeFlag; }
1125 
1126   //! Tests whether the memory operand has a BASE register or label specified.
hasBase()1127   constexpr bool hasBase() const noexcept { return (_signature & kSignatureMemBaseTypeMask) != 0; }
1128   //! Tests whether the memory operand has an INDEX register specified.
hasIndex()1129   constexpr bool hasIndex() const noexcept { return (_signature & kSignatureMemIndexTypeMask) != 0; }
1130   //! Tests whether the memory operand has BASE or INDEX register.
hasBaseOrIndex()1131   constexpr bool hasBaseOrIndex() const noexcept { return (_signature & kSignatureMemBaseIndexMask) != 0; }
1132   //! Tests whether the memory operand has BASE and INDEX register.
hasBaseAndIndex()1133   constexpr bool hasBaseAndIndex() const noexcept { return (_signature & kSignatureMemBaseTypeMask) != 0 && (_signature & kSignatureMemIndexTypeMask) != 0; }
1134 
1135   //! Tests whether the BASE operand is a register (registers start after `kLabelTag`).
hasBaseReg()1136   constexpr bool hasBaseReg() const noexcept { return (_signature & kSignatureMemBaseTypeMask) > (Label::kLabelTag << kSignatureMemBaseTypeShift); }
1137   //! Tests whether the BASE operand is a label.
hasBaseLabel()1138   constexpr bool hasBaseLabel() const noexcept { return (_signature & kSignatureMemBaseTypeMask) == (Label::kLabelTag << kSignatureMemBaseTypeShift); }
1139   //! Tests whether the INDEX operand is a register (registers start after `kLabelTag`).
hasIndexReg()1140   constexpr bool hasIndexReg() const noexcept { return (_signature & kSignatureMemIndexTypeMask) > (Label::kLabelTag << kSignatureMemIndexTypeShift); }
1141 
1142   //! Returns the type of the BASE register (0 if this memory operand doesn't
1143   //! use the BASE register).
1144   //!
1145   //! \note If the returned type is one (a value never associated to a register
1146   //! type) the BASE is not register, but it's a label. One equals to `kLabelTag`.
1147   //! You should always check `hasBaseLabel()` before using `baseId()` result.
baseType()1148   constexpr uint32_t baseType() const noexcept { return _getSignaturePart<kSignatureMemBaseTypeMask>(); }
1149 
1150   //! Returns the type of an INDEX register (0 if this memory operand doesn't
1151   //! use the INDEX register).
indexType()1152   constexpr uint32_t indexType() const noexcept { return _getSignaturePart<kSignatureMemIndexTypeMask>(); }
1153 
1154   //! This is used internally for BASE+INDEX validation.
baseAndIndexTypes()1155   constexpr uint32_t baseAndIndexTypes() const noexcept { return _getSignaturePart<kSignatureMemBaseIndexMask>(); }
1156 
1157   //! Returns both BASE (4:0 bits) and INDEX (9:5 bits) types combined into a
1158   //! single value.
1159   //!
1160   //! \remarks Returns id of the BASE register or label (if the BASE was
1161   //! specified as label).
baseId()1162   constexpr uint32_t baseId() const noexcept { return _baseId; }
1163 
1164   //! Returns the id of the INDEX register.
indexId()1165   constexpr uint32_t indexId() const noexcept { return _data[kDataMemIndexId]; }
1166 
1167   //! Sets the id of the BASE register (without modifying its type).
setBaseId(uint32_t rId)1168   inline void setBaseId(uint32_t rId) noexcept { _baseId = rId; }
1169   //! Sets the id of the INDEX register (without modifying its type).
setIndexId(uint32_t rId)1170   inline void setIndexId(uint32_t rId) noexcept { _data[kDataMemIndexId] = rId; }
1171 
1172   //! Sets the base register to type and id of the given `base` operand.
setBase(const BaseReg & base)1173   inline void setBase(const BaseReg& base) noexcept { return _setBase(base.type(), base.id()); }
1174   //! Sets the index register to type and id of the given `index` operand.
setIndex(const BaseReg & index)1175   inline void setIndex(const BaseReg& index) noexcept { return _setIndex(index.type(), index.id()); }
1176 
1177   //! \cond INTERNAL
_setBase(uint32_t rType,uint32_t rId)1178   inline void _setBase(uint32_t rType, uint32_t rId) noexcept {
1179     _setSignaturePart<kSignatureMemBaseTypeMask>(rType);
1180     _baseId = rId;
1181   }
1182 
_setIndex(uint32_t rType,uint32_t rId)1183   inline void _setIndex(uint32_t rType, uint32_t rId) noexcept {
1184     _setSignaturePart<kSignatureMemIndexTypeMask>(rType);
1185     _data[kDataMemIndexId] = rId;
1186   }
1187   //! \endcond
1188 
1189   //! Resets the memory operand's BASE register or label.
resetBase()1190   inline void resetBase() noexcept { _setBase(0, 0); }
1191   //! Resets the memory operand's INDEX register.
resetIndex()1192   inline void resetIndex() noexcept { _setIndex(0, 0); }
1193 
1194   //! Sets the memory operand size (in bytes).
setSize(uint32_t size)1195   inline void setSize(uint32_t size) noexcept { _setSignaturePart<kSignatureSizeMask>(size); }
1196 
1197   //! Tests whether the memory operand has a 64-bit offset or absolute address.
1198   //!
1199   //! If this is true then `hasBase()` must always report false.
isOffset64Bit()1200   constexpr bool isOffset64Bit() const noexcept { return baseType() == 0; }
1201 
1202   //! Tests whether the memory operand has a non-zero offset or absolute address.
hasOffset()1203   constexpr bool hasOffset() const noexcept {
1204     return (_data[kDataMemOffsetLo] | uint32_t(_baseId & Support::bitMaskFromBool<uint32_t>(isOffset64Bit()))) != 0;
1205   }
1206 
1207   //! Returns either relative offset or absolute address as 64-bit integer.
offset()1208   constexpr int64_t offset() const noexcept {
1209     return isOffset64Bit() ? int64_t(uint64_t(_data[kDataMemOffsetLo]) | (uint64_t(_baseId) << 32))
1210                            : int64_t(int32_t(_data[kDataMemOffsetLo])); // Sign extend 32-bit offset.
1211   }
1212 
1213   //! Returns a 32-bit low part of a 64-bit offset or absolute address.
offsetLo32()1214   constexpr int32_t offsetLo32() const noexcept { return int32_t(_data[kDataMemOffsetLo]); }
1215   //! Returns a 32-but high part of a 64-bit offset or absolute address.
1216   //!
1217   //! \note This function is UNSAFE and returns garbage if `isOffset64Bit()`
1218   //! returns false. Never use it blindly without checking it first.
offsetHi32()1219   constexpr int32_t offsetHi32() const noexcept { return int32_t(_baseId); }
1220 
1221   //! Sets a 64-bit offset or an absolute address to `offset`.
1222   //!
1223   //! \note This functions attempts to set both high and low parts of a 64-bit
1224   //! offset, however, if the operand has a BASE register it will store only the
1225   //! low 32 bits of the offset / address as there is no way to store both BASE
1226   //! and 64-bit offset, and there is currently no architecture that has such
1227   //! capability targeted by AsmJit.
setOffset(int64_t offset)1228   inline void setOffset(int64_t offset) noexcept {
1229     uint32_t lo = uint32_t(uint64_t(offset) & 0xFFFFFFFFu);
1230     uint32_t hi = uint32_t(uint64_t(offset) >> 32);
1231     uint32_t hiMsk = Support::bitMaskFromBool<uint32_t>(isOffset64Bit());
1232 
1233     _data[kDataMemOffsetLo] = lo;
1234     _baseId = (hi & hiMsk) | (_baseId & ~hiMsk);
1235   }
1236   //! Sets a low 32-bit offset to `offset` (don't use without knowing how BaseMem works).
setOffsetLo32(int32_t offset)1237   inline void setOffsetLo32(int32_t offset) noexcept { _data[kDataMemOffsetLo] = uint32_t(offset); }
1238 
1239   //! Adjusts the offset by `offset`.
1240   //!
1241   //! \note This is a fast function that doesn't use the HI 32-bits of a
1242   //! 64-bit offset. Use it only if you know that there is a BASE register
1243   //! and the offset is only 32 bits anyway.
1244 
1245   //! Adjusts the memory operand offset by a `offset`.
addOffset(int64_t offset)1246   inline void addOffset(int64_t offset) noexcept {
1247     if (isOffset64Bit()) {
1248       int64_t result = offset + int64_t(uint64_t(_data[kDataMemOffsetLo]) | (uint64_t(_baseId) << 32));
1249       _data[kDataMemOffsetLo] = uint32_t(uint64_t(result) & 0xFFFFFFFFu);
1250       _baseId                 = uint32_t(uint64_t(result) >> 32);
1251     }
1252     else {
1253       _data[kDataMemOffsetLo] += uint32_t(uint64_t(offset) & 0xFFFFFFFFu);
1254     }
1255   }
1256 
1257   //! Adds `offset` to a low 32-bit offset part (don't use without knowing how
1258   //! BaseMem works).
addOffsetLo32(int32_t offset)1259   inline void addOffsetLo32(int32_t offset) noexcept { _data[kDataMemOffsetLo] += uint32_t(offset); }
1260 
1261   //! Resets the memory offset to zero.
resetOffset()1262   inline void resetOffset() noexcept { setOffset(0); }
1263 
1264   //! Resets the lo part of the memory offset to zero (don't use without knowing
1265   //! how BaseMem works).
resetOffsetLo32()1266   inline void resetOffsetLo32() noexcept { setOffsetLo32(0); }
1267 
1268   //! \}
1269 };
1270 
1271 // ============================================================================
1272 // [asmjit::Imm]
1273 // ============================================================================
1274 
1275 //! Immediate operand.
1276 //!
1277 //! Immediate operand is usually part of instruction itself. It's inlined after
1278 //! or before the instruction opcode. Immediates can be only signed or unsigned
1279 //! integers.
1280 //!
1281 //! To create an immediate operand use `asmjit::imm()` helper, which can be used
1282 //! with any type, not just the default 64-bit int.
1283 class Imm : public Operand {
1284 public:
1285   //! Type of the immediate.
1286   enum Type : uint32_t {
1287     //! Immediate is integer.
1288     kTypeInteger = 0,
1289     //! Immediate is a floating point stored as double-precision.
1290     kTypeDouble = 1
1291   };
1292 
1293   //! \name Construction & Destruction
1294   //! \{
1295 
1296   //! Creates a new immediate value (initial value is 0).
Imm()1297   inline constexpr Imm() noexcept
1298     : Operand(Globals::Init, kOpImm, 0, 0, 0) {}
1299 
1300   //! Creates a new immediate value from `other`.
Imm(const Imm & other)1301   inline constexpr Imm(const Imm& other) noexcept
1302     : Operand(other) {}
1303 
1304   //! Creates a new immediate value from ARM/AArch64 specific `shift`.
Imm(const arm::Shift & shift)1305   inline constexpr Imm(const arm::Shift& shift) noexcept
1306     : Operand(Globals::Init, kOpImm | (shift.op() << kSignaturePredicateShift),
1307               0,
1308               Support::unpackU32At0(shift.value()),
1309               Support::unpackU32At1(shift.value())) {}
1310 
1311   //! Creates a new signed immediate value, assigning the value to `val` and
1312   //! an architecture-specific predicate to `predicate`.
1313   //!
1314   //! \note Predicate is currently only used by ARM architectures.
1315   template<typename T>
1316   inline constexpr Imm(const T& val, const uint32_t predicate = 0) noexcept
1317     : Operand(Globals::Init, kOpImm | (predicate << kSignaturePredicateShift),
1318               0,
1319               Support::unpackU32At0(int64_t(val)),
1320               Support::unpackU32At1(int64_t(val))) {}
1321 
1322   inline Imm(const float& val, const uint32_t predicate = 0) noexcept
1323     : Operand(Globals::Init, kOpImm | (predicate << kSignaturePredicateShift), 0, 0, 0) { setValue(val); }
1324 
1325   inline Imm(const double& val, const uint32_t predicate = 0) noexcept
1326     : Operand(Globals::Init, kOpImm | (predicate << kSignaturePredicateShift), 0, 0, 0) { setValue(val); }
1327 
Imm(Globals::NoInit_)1328   inline explicit Imm(Globals::NoInit_) noexcept
1329     : Operand(Globals::NoInit) {}
1330 
1331   //! \}
1332 
1333   //! \name Overloaded Operators
1334   //! \{
1335 
1336   //! Assigns the value of the `other` operand to this immediate.
1337   inline Imm& operator=(const Imm& other) noexcept { copyFrom(other); return *this; }
1338 
1339   //! \}
1340 
1341   //! \name Accessors
1342   //! \{
1343 
1344   //! Returns immediate type, see \ref Type.
type()1345   constexpr uint32_t type() const noexcept { return _getSignaturePart<kSignatureImmTypeMask>(); }
1346   //! Sets the immediate type to `type`, see \ref Type.
setType(uint32_t type)1347   inline void setType(uint32_t type) noexcept { _setSignaturePart<kSignatureImmTypeMask>(type); }
1348   //! Resets immediate type to `kTypeInteger`.
resetType()1349   inline void resetType() noexcept { setType(kTypeInteger); }
1350 
1351   //! Returns operation predicate of the immediate.
1352   //!
1353   //! The meaning depends on architecture, for example on ARM hardware this
1354   //! describes \ref arm::Predicate::ShiftOp of the immediate.
predicate()1355   constexpr uint32_t predicate() const noexcept { return _getSignaturePart<kSignaturePredicateMask>(); }
1356 
1357   //! Sets operation predicate of the immediate to `predicate`.
1358   //!
1359   //! The meaning depends on architecture, for example on ARM hardware this
1360   //! describes \ref arm::Predicate::ShiftOp of the immediate.
setPredicate(uint32_t predicate)1361   inline void setPredicate(uint32_t predicate) noexcept { _setSignaturePart<kSignaturePredicateMask>(predicate); }
1362 
1363   //! Resets the shift operation type of the immediate to the default value (no operation).
resetPredicate()1364   inline void resetPredicate() noexcept { _setSignaturePart<kSignaturePredicateMask>(0); }
1365 
1366   //! Returns the immediate value as `int64_t`, which is the internal format Imm uses.
value()1367   constexpr int64_t value() const noexcept {
1368     return int64_t((uint64_t(_data[kDataImmValueHi]) << 32) | _data[kDataImmValueLo]);
1369   }
1370 
1371   //! Tests whether this immediate value is integer of any size.
isInteger()1372   constexpr uint32_t isInteger() const noexcept { return type() == kTypeInteger; }
1373   //! Tests whether this immediate value is a double precision floating point value.
isDouble()1374   constexpr uint32_t isDouble() const noexcept { return type() == kTypeDouble; }
1375 
1376   //! Tests whether the immediate can be casted to 8-bit signed integer.
isInt8()1377   constexpr bool isInt8() const noexcept { return type() == kTypeInteger && Support::isInt8(value()); }
1378   //! Tests whether the immediate can be casted to 8-bit unsigned integer.
isUInt8()1379   constexpr bool isUInt8() const noexcept { return type() == kTypeInteger && Support::isUInt8(value()); }
1380   //! Tests whether the immediate can be casted to 16-bit signed integer.
isInt16()1381   constexpr bool isInt16() const noexcept { return type() == kTypeInteger && Support::isInt16(value()); }
1382   //! Tests whether the immediate can be casted to 16-bit unsigned integer.
isUInt16()1383   constexpr bool isUInt16() const noexcept { return type() == kTypeInteger && Support::isUInt16(value()); }
1384   //! Tests whether the immediate can be casted to 32-bit signed integer.
isInt32()1385   constexpr bool isInt32() const noexcept { return type() == kTypeInteger && Support::isInt32(value()); }
1386   //! Tests whether the immediate can be casted to 32-bit unsigned integer.
isUInt32()1387   constexpr bool isUInt32() const noexcept { return type() == kTypeInteger && _data[kDataImmValueHi] == 0; }
1388 
1389   //! Returns the immediate value casted to `T`.
1390   //!
1391   //! The value is masked before it's casted to `T` so the returned value is
1392   //! simply the representation of `T` considering the original value's lowest
1393   //! bits.
1394   template<typename T>
valueAs()1395   inline T valueAs() const noexcept { return Support::immediateToT<T>(value()); }
1396 
1397   //! Returns low 32-bit signed integer.
int32Lo()1398   constexpr int32_t int32Lo() const noexcept { return int32_t(_data[kDataImmValueLo]); }
1399   //! Returns high 32-bit signed integer.
int32Hi()1400   constexpr int32_t int32Hi() const noexcept { return int32_t(_data[kDataImmValueHi]); }
1401   //! Returns low 32-bit signed integer.
uint32Lo()1402   constexpr uint32_t uint32Lo() const noexcept { return _data[kDataImmValueLo]; }
1403   //! Returns high 32-bit signed integer.
uint32Hi()1404   constexpr uint32_t uint32Hi() const noexcept { return _data[kDataImmValueHi]; }
1405 
1406   //! Sets immediate value to `val`, the value is casted to a signed 64-bit integer.
1407   template<typename T>
setValue(const T & val)1408   inline void setValue(const T& val) noexcept {
1409     _setValueInternal(Support::immediateFromT(val), std::is_floating_point<T>::value ? kTypeDouble : kTypeInteger);
1410   }
1411 
_setValueInternal(int64_t val,uint32_t type)1412   inline void _setValueInternal(int64_t val, uint32_t type) noexcept {
1413     setType(type);
1414     _data[kDataImmValueHi] = uint32_t(uint64_t(val) >> 32);
1415     _data[kDataImmValueLo] = uint32_t(uint64_t(val) & 0xFFFFFFFFu);
1416   }
1417 
1418   //! \}
1419 
1420   //! \name Utilities
1421   //! \{
1422 
1423   //! Clones the immediate operand.
clone()1424   constexpr Imm clone() const noexcept { return Imm(*this); }
1425 
signExtend8Bits()1426   inline void signExtend8Bits() noexcept { setValue(int64_t(valueAs<int8_t>())); }
signExtend16Bits()1427   inline void signExtend16Bits() noexcept { setValue(int64_t(valueAs<int16_t>())); }
signExtend32Bits()1428   inline void signExtend32Bits() noexcept { setValue(int64_t(valueAs<int32_t>())); }
1429 
zeroExtend8Bits()1430   inline void zeroExtend8Bits() noexcept { setValue(valueAs<uint8_t>()); }
zeroExtend16Bits()1431   inline void zeroExtend16Bits() noexcept { setValue(valueAs<uint16_t>()); }
zeroExtend32Bits()1432   inline void zeroExtend32Bits() noexcept { _data[kDataImmValueHi] = 0u; }
1433 
1434   //! \}
1435 
1436 #ifndef ASMJIT_NO_DEPRECATED
1437   ASMJIT_DEPRECATED("Use valueAs<int8_t>() instead")
i8()1438   inline int8_t i8() const noexcept { return valueAs<int8_t>(); }
1439 
1440   ASMJIT_DEPRECATED("Use valueAs<uint8_t>() instead")
u8()1441   inline uint8_t u8() const noexcept { return valueAs<uint8_t>(); }
1442 
1443   ASMJIT_DEPRECATED("Use valueAs<int16_t>() instead")
i16()1444   inline int16_t i16() const noexcept { return valueAs<int16_t>(); }
1445 
1446   ASMJIT_DEPRECATED("Use valueAs<uint16_t>() instead")
u16()1447   inline uint16_t u16() const noexcept { return valueAs<uint16_t>(); }
1448 
1449   ASMJIT_DEPRECATED("Use valueAs<int32_t>() instead")
i32()1450   inline int32_t i32() const noexcept { return valueAs<int32_t>(); }
1451 
1452   ASMJIT_DEPRECATED("Use valueAs<uint32_t>() instead")
u32()1453   inline uint32_t u32() const noexcept { return valueAs<uint32_t>(); }
1454 
1455   ASMJIT_DEPRECATED("Use value() instead")
i64()1456   inline int64_t i64() const noexcept { return value(); }
1457 
1458   ASMJIT_DEPRECATED("Use valueAs<uint64_t>() instead")
u64()1459   inline uint64_t u64() const noexcept { return valueAs<uint64_t>(); }
1460 
1461   ASMJIT_DEPRECATED("Use valueAs<intptr_t>() instead")
iptr()1462   inline intptr_t iptr() const noexcept { return valueAs<intptr_t>(); }
1463 
1464   ASMJIT_DEPRECATED("Use valueAs<uintptr_t>() instead")
uptr()1465   inline uintptr_t uptr() const noexcept { return valueAs<uintptr_t>(); }
1466 
1467   ASMJIT_DEPRECATED("Use int32Lo() instead")
i32Lo()1468   inline int32_t i32Lo() const noexcept { return int32Lo(); }
1469 
1470   ASMJIT_DEPRECATED("Use uint32Lo() instead")
u32Lo()1471   inline uint32_t u32Lo() const noexcept { return uint32Lo(); }
1472 
1473   ASMJIT_DEPRECATED("Use int32Hi() instead")
i32Hi()1474   inline int32_t i32Hi() const noexcept { return int32Hi(); }
1475 
1476   ASMJIT_DEPRECATED("Use uint32Hi() instead")
u32Hi()1477   inline uint32_t u32Hi() const noexcept { return uint32Hi(); }
1478 #endif // !ASMJIT_NO_DEPRECATED
1479 };
1480 
1481 //! Creates a new immediate operand.
1482 //!
1483 //! Using `imm(x)` is much nicer than using `Imm(x)` as this is a template
1484 //! which can accept any integer including pointers and function pointers.
1485 template<typename T>
imm(const T & val)1486 static constexpr Imm imm(const T& val) noexcept { return Imm(val); }
1487 
1488 //! \}
1489 
1490 // ============================================================================
1491 // [asmjit::Globals::none]
1492 // ============================================================================
1493 
1494 namespace Globals {
1495   //! \ingroup asmjit_assembler
1496   //!
1497   //! A default-constructed operand of `Operand_::kOpNone` type.
1498   static constexpr const Operand none;
1499 }
1500 
1501 // ============================================================================
1502 // [asmjit::Support::ForwardOp]
1503 // ============================================================================
1504 
1505 //! \cond INTERNAL
1506 namespace Support {
1507 
1508 template<typename T, bool IsIntegral>
1509 struct ForwardOpImpl {
forwardForwardOpImpl1510   static ASMJIT_INLINE const T& forward(const T& value) noexcept { return value; }
1511 };
1512 
1513 template<typename T>
1514 struct ForwardOpImpl<T, true> {
1515   static ASMJIT_INLINE Imm forward(const T& value) noexcept { return Imm(value); }
1516 };
1517 
1518 //! Either forwards operand T or returns a new operand for T if T is a type
1519 //! convertible to operand. At the moment this is only used to convert integers
1520 //! to \ref Imm operands.
1521 template<typename T>
1522 struct ForwardOp : public ForwardOpImpl<T, std::is_integral<typename std::decay<T>::type>::value> {};
1523 
1524 }
1525 
1526 //! \endcond
1527 
1528 ASMJIT_END_NAMESPACE
1529 
1530 #endif // ASMJIT_CORE_OPERAND_H_INCLUDED
1531