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_X86_X86OPERAND_H_INCLUDED
25 #define ASMJIT_X86_X86OPERAND_H_INCLUDED
26 
27 #include "../core/archtraits.h"
28 #include "../core/operand.h"
29 #include "../core/type.h"
30 #include "../x86/x86globals.h"
31 
32 ASMJIT_BEGIN_SUB_NAMESPACE(x86)
33 
34 #define ASMJIT_MEM_PTR(FUNC, SIZE)                                                    \
35   static constexpr Mem FUNC(const Gp& base, int32_t offset = 0) noexcept {            \
36     return Mem(base, offset, SIZE);                                                   \
37   }                                                                                   \
38   static constexpr Mem FUNC(const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \
39     return Mem(base, index, shift, offset, SIZE);                                     \
40   }                                                                                   \
41   static constexpr Mem FUNC(const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \
42     return Mem(base, index, shift, offset, SIZE);                                     \
43   }                                                                                   \
44   static constexpr Mem FUNC(const Label& base, int32_t offset = 0) noexcept {         \
45     return Mem(base, offset, SIZE);                                                   \
46   }                                                                                   \
47   static constexpr Mem FUNC(const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \
48     return Mem(base, index, shift, offset, SIZE);                                     \
49   }                                                                                   \
50   static constexpr Mem FUNC(const Rip& rip_, int32_t offset = 0) noexcept {           \
51     return Mem(rip_, offset, SIZE);                                                   \
52   }                                                                                   \
53   static constexpr Mem FUNC(uint64_t base) noexcept {                                 \
54     return Mem(base, SIZE);                                                           \
55   }                                                                                   \
56   static constexpr Mem FUNC(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \
57     return Mem(base, index, shift, SIZE);                                             \
58   }                                                                                   \
59   static constexpr Mem FUNC(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \
60     return Mem(base, index, shift, SIZE);                                             \
61   }                                                                                   \
62                                                                                       \
63   static constexpr Mem FUNC##_abs(uint64_t base) noexcept {                           \
64     return Mem(base, SIZE, Mem::kSignatureMemAbs);                                    \
65   }                                                                                   \
66   static constexpr Mem FUNC##_abs(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \
67     return Mem(base, index, shift, SIZE, Mem::kSignatureMemAbs);                      \
68   }                                                                                   \
69   static constexpr Mem FUNC##_abs(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \
70     return Mem(base, index, shift, SIZE, Mem::kSignatureMemAbs);                      \
71   }                                                                                   \
72                                                                                       \
73   static constexpr Mem FUNC##_rel(uint64_t base) noexcept {                           \
74     return Mem(base, SIZE, Mem::kSignatureMemRel);                                    \
75   }                                                                                   \
76   static constexpr Mem FUNC##_rel(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \
77     return Mem(base, index, shift, SIZE, Mem::kSignatureMemRel);                      \
78   }                                                                                   \
79   static constexpr Mem FUNC##_rel(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \
80     return Mem(base, index, shift, SIZE, Mem::kSignatureMemRel);                      \
81   }
82 
83 //! \addtogroup asmjit_x86
84 //! \{
85 
86 // ============================================================================
87 // [Forward Declarations]
88 // ============================================================================
89 
90 class Reg;
91 class Mem;
92 
93 class Gp;
94 class Gpb;
95 class GpbLo;
96 class GpbHi;
97 class Gpw;
98 class Gpd;
99 class Gpq;
100 class Vec;
101 class Xmm;
102 class Ymm;
103 class Zmm;
104 class Mm;
105 class KReg;
106 class SReg;
107 class CReg;
108 class DReg;
109 class St;
110 class Bnd;
111 class Tmm;
112 class Rip;
113 
114 // ============================================================================
115 // [asmjit::x86::Reg]
116 // ============================================================================
117 
118 //! Register traits (X86).
119 //!
120 //! Register traits contains information about a particular register type. It's
121 //! used by asmjit to setup register information on-the-fly and to populate
122 //! tables that contain register information (this way it's possible to change
123 //! register types and groups without having to reorder these tables).
124 template<uint32_t REG_TYPE>
125 struct RegTraits : public BaseRegTraits {};
126 
127 //! \cond
128 // <--------------------+-----+-------------------------+------------------------+---+---+----------------+
129 //                      | Reg |        Reg-Type         |        Reg-Group       |Sz |Cnt|     TypeId     |
130 // <--------------------+-----+-------------------------+------------------------+---+---+----------------+
131 ASMJIT_DEFINE_REG_TRAITS(GpbLo, BaseReg::kTypeGp8Lo     , BaseReg::kGroupGp      , 1 , 16, Type::kIdI8    );
132 ASMJIT_DEFINE_REG_TRAITS(GpbHi, BaseReg::kTypeGp8Hi     , BaseReg::kGroupGp      , 1 , 4 , Type::kIdI8    );
133 ASMJIT_DEFINE_REG_TRAITS(Gpw  , BaseReg::kTypeGp16      , BaseReg::kGroupGp      , 2 , 16, Type::kIdI16   );
134 ASMJIT_DEFINE_REG_TRAITS(Gpd  , BaseReg::kTypeGp32      , BaseReg::kGroupGp      , 4 , 16, Type::kIdI32   );
135 ASMJIT_DEFINE_REG_TRAITS(Gpq  , BaseReg::kTypeGp64      , BaseReg::kGroupGp      , 8 , 16, Type::kIdI64   );
136 ASMJIT_DEFINE_REG_TRAITS(Xmm  , BaseReg::kTypeVec128    , BaseReg::kGroupVec     , 16, 32, Type::kIdI32x4 );
137 ASMJIT_DEFINE_REG_TRAITS(Ymm  , BaseReg::kTypeVec256    , BaseReg::kGroupVec     , 32, 32, Type::kIdI32x8 );
138 ASMJIT_DEFINE_REG_TRAITS(Zmm  , BaseReg::kTypeVec512    , BaseReg::kGroupVec     , 64, 32, Type::kIdI32x16);
139 ASMJIT_DEFINE_REG_TRAITS(Mm   , BaseReg::kTypeOther0    , BaseReg::kGroupOther0  , 8 , 8 , Type::kIdMmx64 );
140 ASMJIT_DEFINE_REG_TRAITS(KReg , BaseReg::kTypeOther1    , BaseReg::kGroupOther1  , 0 , 8 , Type::kIdVoid  );
141 ASMJIT_DEFINE_REG_TRAITS(SReg , BaseReg::kTypeCustom + 0, BaseReg::kGroupVirt + 0, 2 , 7 , Type::kIdVoid  );
142 ASMJIT_DEFINE_REG_TRAITS(CReg , BaseReg::kTypeCustom + 1, BaseReg::kGroupVirt + 1, 0 , 16, Type::kIdVoid  );
143 ASMJIT_DEFINE_REG_TRAITS(DReg , BaseReg::kTypeCustom + 2, BaseReg::kGroupVirt + 2, 0 , 16, Type::kIdVoid  );
144 ASMJIT_DEFINE_REG_TRAITS(St   , BaseReg::kTypeCustom + 3, BaseReg::kGroupVirt + 3, 10, 8 , Type::kIdF80   );
145 ASMJIT_DEFINE_REG_TRAITS(Bnd  , BaseReg::kTypeCustom + 4, BaseReg::kGroupVirt + 4, 16, 4 , Type::kIdVoid  );
146 ASMJIT_DEFINE_REG_TRAITS(Tmm  , BaseReg::kTypeCustom + 5, BaseReg::kGroupVirt + 5, 0 , 8 , Type::kIdVoid  );
147 ASMJIT_DEFINE_REG_TRAITS(Rip  , BaseReg::kTypeIP        , BaseReg::kGroupVirt + 6, 0 , 1 , Type::kIdVoid  );
148 //! \endcond
149 
150 //! Register (X86).
151 class Reg : public BaseReg {
152 public:
153   ASMJIT_DEFINE_ABSTRACT_REG(Reg, BaseReg)
154 
155   //! Register type.
156   enum RegType : uint32_t {
157     //! No register type or invalid register.
158     kTypeNone = BaseReg::kTypeNone,
159 
160     //! Low GPB register (AL, BL, CL, DL, ...).
161     kTypeGpbLo = BaseReg::kTypeGp8Lo,
162     //! High GPB register (AH, BH, CH, DH only).
163     kTypeGpbHi = BaseReg::kTypeGp8Hi,
164     //! GPW register.
165     kTypeGpw = BaseReg::kTypeGp16,
166     //! GPD register.
167     kTypeGpd = BaseReg::kTypeGp32,
168     //! GPQ register (64-bit).
169     kTypeGpq = BaseReg::kTypeGp64,
170     //! XMM register (SSE+).
171     kTypeXmm = BaseReg::kTypeVec128,
172     //! YMM register (AVX+).
173     kTypeYmm = BaseReg::kTypeVec256,
174     //! ZMM register (AVX512+).
175     kTypeZmm = BaseReg::kTypeVec512,
176     //! MMX register.
177     kTypeMm = BaseReg::kTypeOther0,
178     //! K register (AVX512+).
179     kTypeKReg = BaseReg::kTypeOther1,
180     //! Instruction pointer (EIP, RIP).
181     kTypeRip = BaseReg::kTypeIP,
182     //! Segment register (None, ES, CS, SS, DS, FS, GS).
183     kTypeSReg = BaseReg::kTypeCustom + 0,
184     //! Control register (CR).
185     kTypeCReg = BaseReg::kTypeCustom + 1,
186     //! Debug register (DR).
187     kTypeDReg = BaseReg::kTypeCustom + 2,
188     //! FPU (x87) register.
189     kTypeSt = BaseReg::kTypeCustom + 3,
190     //! Bound register (BND).
191     kTypeBnd = BaseReg::kTypeCustom + 4,
192     //! TMM register (AMX_TILE)
193     kTypeTmm = BaseReg::kTypeCustom + 5,
194 
195     //! Count of register types.
196     kTypeCount = BaseReg::kTypeCustom + 6
197   };
198 
199   //! Register group.
200   enum RegGroup : uint32_t {
201     //! GP register group or none (universal).
202     kGroupGp   = BaseReg::kGroupGp,
203     //! XMM|YMM|ZMM register group (universal).
204     kGroupVec  = BaseReg::kGroupVec,
205     //! MMX register group (legacy).
206     kGroupMm   = BaseReg::kGroupOther0,
207     //! K register group.
208     kGroupKReg = BaseReg::kGroupOther1,
209 
210     // These are not managed by Compiler nor used by Func-API:
211 
212     //! Segment register group.
213     kGroupSReg = BaseReg::kGroupVirt+0,
214     //! Control register group.
215     kGroupCReg = BaseReg::kGroupVirt+1,
216     //! Debug register group.
217     kGroupDReg = BaseReg::kGroupVirt+2,
218     //! FPU register group.
219     kGroupSt   = BaseReg::kGroupVirt+3,
220     //! Bound register group.
221     kGroupBnd  = BaseReg::kGroupVirt+4,
222     //! TMM register group.
223     kGroupTmm  = BaseReg::kGroupVirt+5,
224     //! Instrucion pointer (IP).
225     kGroupRip  = BaseReg::kGroupVirt+6,
226 
227     //! Count of all register groups.
228     kGroupCount
229   };
230 
231   //! Tests whether the register is a GPB register (8-bit).
isGpb()232   constexpr bool isGpb() const noexcept { return size() == 1; }
233   //! Tests whether the register is a low GPB register (8-bit).
isGpbLo()234   constexpr bool isGpbLo() const noexcept { return hasBaseSignature(RegTraits<kTypeGpbLo>::kSignature); }
235   //! Tests whether the register is a high GPB register (8-bit).
isGpbHi()236   constexpr bool isGpbHi() const noexcept { return hasBaseSignature(RegTraits<kTypeGpbHi>::kSignature); }
237   //! Tests whether the register is a GPW register (16-bit).
isGpw()238   constexpr bool isGpw() const noexcept { return hasBaseSignature(RegTraits<kTypeGpw>::kSignature); }
239   //! Tests whether the register is a GPD register (32-bit).
isGpd()240   constexpr bool isGpd() const noexcept { return hasBaseSignature(RegTraits<kTypeGpd>::kSignature); }
241   //! Tests whether the register is a GPQ register (64-bit).
isGpq()242   constexpr bool isGpq() const noexcept { return hasBaseSignature(RegTraits<kTypeGpq>::kSignature); }
243   //! Tests whether the register is an XMM register (128-bit).
isXmm()244   constexpr bool isXmm() const noexcept { return hasBaseSignature(RegTraits<kTypeXmm>::kSignature); }
245   //! Tests whether the register is a YMM register (256-bit).
isYmm()246   constexpr bool isYmm() const noexcept { return hasBaseSignature(RegTraits<kTypeYmm>::kSignature); }
247   //! Tests whether the register is a ZMM register (512-bit).
isZmm()248   constexpr bool isZmm() const noexcept { return hasBaseSignature(RegTraits<kTypeZmm>::kSignature); }
249   //! Tests whether the register is an MMX register (64-bit).
isMm()250   constexpr bool isMm() const noexcept { return hasBaseSignature(RegTraits<kTypeMm>::kSignature); }
251   //! Tests whether the register is a K register (64-bit).
isKReg()252   constexpr bool isKReg() const noexcept { return hasBaseSignature(RegTraits<kTypeKReg>::kSignature); }
253   //! Tests whether the register is a segment register.
isSReg()254   constexpr bool isSReg() const noexcept { return hasBaseSignature(RegTraits<kTypeSReg>::kSignature); }
255   //! Tests whether the register is a control register.
isCReg()256   constexpr bool isCReg() const noexcept { return hasBaseSignature(RegTraits<kTypeCReg>::kSignature); }
257   //! Tests whether the register is a debug register.
isDReg()258   constexpr bool isDReg() const noexcept { return hasBaseSignature(RegTraits<kTypeDReg>::kSignature); }
259   //! Tests whether the register is an FPU register (80-bit).
isSt()260   constexpr bool isSt() const noexcept { return hasBaseSignature(RegTraits<kTypeSt>::kSignature); }
261   //! Tests whether the register is a bound register.
isBnd()262   constexpr bool isBnd() const noexcept { return hasBaseSignature(RegTraits<kTypeBnd>::kSignature); }
263   //! Tests whether the register is a TMM register.
isTmm()264   constexpr bool isTmm() const noexcept { return hasBaseSignature(RegTraits<kTypeTmm>::kSignature); }
265   //! Tests whether the register is RIP.
isRip()266   constexpr bool isRip() const noexcept { return hasBaseSignature(RegTraits<kTypeRip>::kSignature); }
267 
268   template<uint32_t REG_TYPE>
setRegT(uint32_t rId)269   inline void setRegT(uint32_t rId) noexcept {
270     setSignature(RegTraits<REG_TYPE>::kSignature);
271     setId(rId);
272   }
273 
setTypeAndId(uint32_t rType,uint32_t rId)274   inline void setTypeAndId(uint32_t rType, uint32_t rId) noexcept {
275     ASMJIT_ASSERT(rType < kTypeCount);
276     setSignature(signatureOf(rType));
277     setId(rId);
278   }
279 
groupOf(uint32_t rType)280   static inline uint32_t groupOf(uint32_t rType) noexcept { return _archTraits[Environment::kArchX86].regTypeToGroup(rType); }
typeIdOf(uint32_t rType)281   static inline uint32_t typeIdOf(uint32_t rType) noexcept { return _archTraits[Environment::kArchX86].regTypeToTypeId(rType); }
signatureOf(uint32_t rType)282   static inline uint32_t signatureOf(uint32_t rType) noexcept { return _archTraits[Environment::kArchX86].regTypeToSignature(rType); }
283 
284   template<uint32_t REG_TYPE>
groupOfT()285   static inline uint32_t groupOfT() noexcept { return RegTraits<REG_TYPE>::kGroup; }
286 
287   template<uint32_t REG_TYPE>
typeIdOfT()288   static inline uint32_t typeIdOfT() noexcept { return RegTraits<REG_TYPE>::kTypeId; }
289 
290   template<uint32_t REG_TYPE>
signatureOfT()291   static inline uint32_t signatureOfT() noexcept { return RegTraits<REG_TYPE>::kSignature; }
292 
signatureOfVecByType(uint32_t typeId)293   static inline uint32_t signatureOfVecByType(uint32_t typeId) noexcept {
294     return typeId <= Type::_kIdVec128End ? RegTraits<kTypeXmm>::kSignature :
295            typeId <= Type::_kIdVec256End ? RegTraits<kTypeYmm>::kSignature : RegTraits<kTypeZmm>::kSignature;
296   }
297 
signatureOfVecBySize(uint32_t size)298   static inline uint32_t signatureOfVecBySize(uint32_t size) noexcept {
299     return size <= 16 ? RegTraits<kTypeXmm>::kSignature :
300            size <= 32 ? RegTraits<kTypeYmm>::kSignature : RegTraits<kTypeZmm>::kSignature;
301   }
302 
303   //! Tests whether the `op` operand is either a low or high 8-bit GPB register.
isGpb(const Operand_ & op)304   static inline bool isGpb(const Operand_& op) noexcept {
305     // Check operand type, register group, and size. Not interested in register type.
306     const uint32_t kSgn = (Operand::kOpReg << kSignatureOpTypeShift) |
307                           (1               << kSignatureSizeShift  ) ;
308     return (op.signature() & (kSignatureOpTypeMask | kSignatureSizeMask)) == kSgn;
309   }
310 
isGpbLo(const Operand_ & op)311   static inline bool isGpbLo(const Operand_& op) noexcept { return op.as<Reg>().isGpbLo(); }
isGpbHi(const Operand_ & op)312   static inline bool isGpbHi(const Operand_& op) noexcept { return op.as<Reg>().isGpbHi(); }
isGpw(const Operand_ & op)313   static inline bool isGpw(const Operand_& op) noexcept { return op.as<Reg>().isGpw(); }
isGpd(const Operand_ & op)314   static inline bool isGpd(const Operand_& op) noexcept { return op.as<Reg>().isGpd(); }
isGpq(const Operand_ & op)315   static inline bool isGpq(const Operand_& op) noexcept { return op.as<Reg>().isGpq(); }
isXmm(const Operand_ & op)316   static inline bool isXmm(const Operand_& op) noexcept { return op.as<Reg>().isXmm(); }
isYmm(const Operand_ & op)317   static inline bool isYmm(const Operand_& op) noexcept { return op.as<Reg>().isYmm(); }
isZmm(const Operand_ & op)318   static inline bool isZmm(const Operand_& op) noexcept { return op.as<Reg>().isZmm(); }
isMm(const Operand_ & op)319   static inline bool isMm(const Operand_& op) noexcept { return op.as<Reg>().isMm(); }
isKReg(const Operand_ & op)320   static inline bool isKReg(const Operand_& op) noexcept { return op.as<Reg>().isKReg(); }
isSReg(const Operand_ & op)321   static inline bool isSReg(const Operand_& op) noexcept { return op.as<Reg>().isSReg(); }
isCReg(const Operand_ & op)322   static inline bool isCReg(const Operand_& op) noexcept { return op.as<Reg>().isCReg(); }
isDReg(const Operand_ & op)323   static inline bool isDReg(const Operand_& op) noexcept { return op.as<Reg>().isDReg(); }
isSt(const Operand_ & op)324   static inline bool isSt(const Operand_& op) noexcept { return op.as<Reg>().isSt(); }
isBnd(const Operand_ & op)325   static inline bool isBnd(const Operand_& op) noexcept { return op.as<Reg>().isBnd(); }
isTmm(const Operand_ & op)326   static inline bool isTmm(const Operand_& op) noexcept { return op.as<Reg>().isTmm(); }
isRip(const Operand_ & op)327   static inline bool isRip(const Operand_& op) noexcept { return op.as<Reg>().isRip(); }
328 
isGpb(const Operand_ & op,uint32_t rId)329   static inline bool isGpb(const Operand_& op, uint32_t rId) noexcept { return isGpb(op) & (op.id() == rId); }
isGpbLo(const Operand_ & op,uint32_t rId)330   static inline bool isGpbLo(const Operand_& op, uint32_t rId) noexcept { return isGpbLo(op) & (op.id() == rId); }
isGpbHi(const Operand_ & op,uint32_t rId)331   static inline bool isGpbHi(const Operand_& op, uint32_t rId) noexcept { return isGpbHi(op) & (op.id() == rId); }
isGpw(const Operand_ & op,uint32_t rId)332   static inline bool isGpw(const Operand_& op, uint32_t rId) noexcept { return isGpw(op) & (op.id() == rId); }
isGpd(const Operand_ & op,uint32_t rId)333   static inline bool isGpd(const Operand_& op, uint32_t rId) noexcept { return isGpd(op) & (op.id() == rId); }
isGpq(const Operand_ & op,uint32_t rId)334   static inline bool isGpq(const Operand_& op, uint32_t rId) noexcept { return isGpq(op) & (op.id() == rId); }
isXmm(const Operand_ & op,uint32_t rId)335   static inline bool isXmm(const Operand_& op, uint32_t rId) noexcept { return isXmm(op) & (op.id() == rId); }
isYmm(const Operand_ & op,uint32_t rId)336   static inline bool isYmm(const Operand_& op, uint32_t rId) noexcept { return isYmm(op) & (op.id() == rId); }
isZmm(const Operand_ & op,uint32_t rId)337   static inline bool isZmm(const Operand_& op, uint32_t rId) noexcept { return isZmm(op) & (op.id() == rId); }
isMm(const Operand_ & op,uint32_t rId)338   static inline bool isMm(const Operand_& op, uint32_t rId) noexcept { return isMm(op) & (op.id() == rId); }
isKReg(const Operand_ & op,uint32_t rId)339   static inline bool isKReg(const Operand_& op, uint32_t rId) noexcept { return isKReg(op) & (op.id() == rId); }
isSReg(const Operand_ & op,uint32_t rId)340   static inline bool isSReg(const Operand_& op, uint32_t rId) noexcept { return isSReg(op) & (op.id() == rId); }
isCReg(const Operand_ & op,uint32_t rId)341   static inline bool isCReg(const Operand_& op, uint32_t rId) noexcept { return isCReg(op) & (op.id() == rId); }
isDReg(const Operand_ & op,uint32_t rId)342   static inline bool isDReg(const Operand_& op, uint32_t rId) noexcept { return isDReg(op) & (op.id() == rId); }
isSt(const Operand_ & op,uint32_t rId)343   static inline bool isSt(const Operand_& op, uint32_t rId) noexcept { return isSt(op) & (op.id() == rId); }
isBnd(const Operand_ & op,uint32_t rId)344   static inline bool isBnd(const Operand_& op, uint32_t rId) noexcept { return isBnd(op) & (op.id() == rId); }
isTmm(const Operand_ & op,uint32_t rId)345   static inline bool isTmm(const Operand_& op, uint32_t rId) noexcept { return isTmm(op) & (op.id() == rId); }
isRip(const Operand_ & op,uint32_t rId)346   static inline bool isRip(const Operand_& op, uint32_t rId) noexcept { return isRip(op) & (op.id() == rId); }
347 };
348 
349 //! General purpose register (X86).
350 class Gp : public Reg {
351 public:
352   ASMJIT_DEFINE_ABSTRACT_REG(Gp, Reg)
353 
354   //! Physical id (X86).
355   //!
356   //! \note Register indexes have been reduced to only support general purpose
357   //! registers. There is no need to have enumerations with number suffix that
358   //! expands to the exactly same value as the suffix value itself.
359   enum Id : uint32_t {
360     kIdAx  = 0,  //!< Physical id of AL|AH|AX|EAX|RAX registers.
361     kIdCx  = 1,  //!< Physical id of CL|CH|CX|ECX|RCX registers.
362     kIdDx  = 2,  //!< Physical id of DL|DH|DX|EDX|RDX registers.
363     kIdBx  = 3,  //!< Physical id of BL|BH|BX|EBX|RBX registers.
364     kIdSp  = 4,  //!< Physical id of SPL|SP|ESP|RSP registers.
365     kIdBp  = 5,  //!< Physical id of BPL|BP|EBP|RBP registers.
366     kIdSi  = 6,  //!< Physical id of SIL|SI|ESI|RSI registers.
367     kIdDi  = 7,  //!< Physical id of DIL|DI|EDI|RDI registers.
368     kIdR8  = 8,  //!< Physical id of R8B|R8W|R8D|R8 registers (64-bit only).
369     kIdR9  = 9,  //!< Physical id of R9B|R9W|R9D|R9 registers (64-bit only).
370     kIdR10 = 10, //!< Physical id of R10B|R10W|R10D|R10 registers (64-bit only).
371     kIdR11 = 11, //!< Physical id of R11B|R11W|R11D|R11 registers (64-bit only).
372     kIdR12 = 12, //!< Physical id of R12B|R12W|R12D|R12 registers (64-bit only).
373     kIdR13 = 13, //!< Physical id of R13B|R13W|R13D|R13 registers (64-bit only).
374     kIdR14 = 14, //!< Physical id of R14B|R14W|R14D|R14 registers (64-bit only).
375     kIdR15 = 15  //!< Physical id of R15B|R15W|R15D|R15 registers (64-bit only).
376   };
377 
378   //! Casts this register to 8-bit (LO) part.
379   inline GpbLo r8() const noexcept;
380   //! Casts this register to 8-bit (LO) part.
381   inline GpbLo r8Lo() const noexcept;
382   //! Casts this register to 8-bit (HI) part.
383   inline GpbHi r8Hi() const noexcept;
384   //! Casts this register to 16-bit.
385   inline Gpw r16() const noexcept;
386   //! Casts this register to 32-bit.
387   inline Gpd r32() const noexcept;
388   //! Casts this register to 64-bit.
389   inline Gpq r64() const noexcept;
390 };
391 
392 //! Vector register (XMM|YMM|ZMM) (X86).
393 class Vec : public Reg {
394   ASMJIT_DEFINE_ABSTRACT_REG(Vec, Reg)
395 
396   //! Casts this register to XMM (clone).
397   inline Xmm xmm() const noexcept;
398   //! Casts this register to YMM.
399   inline Ymm ymm() const noexcept;
400   //! Casts this register to ZMM.
401   inline Zmm zmm() const noexcept;
402 
403   //! Casts this register to a register that has half the size (or XMM if it's already XMM).
half()404   inline Vec half() const noexcept {
405     return Vec::fromSignatureAndId(type() == kTypeZmm ? signatureOfT<kTypeYmm>() : signatureOfT<kTypeXmm>(), id());
406   }
407 };
408 
409 //! Segment register (X86).
410 class SReg : public Reg {
411   ASMJIT_DEFINE_FINAL_REG(SReg, Reg, RegTraits<kTypeSReg>)
412 
413   //! X86 segment id.
414   enum Id : uint32_t {
415     //! No segment (default).
416     kIdNone = 0,
417     //! ES segment.
418     kIdEs = 1,
419     //! CS segment.
420     kIdCs = 2,
421     //! SS segment.
422     kIdSs = 3,
423     //! DS segment.
424     kIdDs = 4,
425     //! FS segment.
426     kIdFs = 5,
427     //! GS segment.
428     kIdGs = 6,
429 
430     //! Count of X86 segment registers supported by AsmJit.
431     //!
432     //! \note X86 architecture has 6 segment registers - ES, CS, SS, DS, FS, GS.
433     //! X64 architecture lowers them down to just FS and GS. AsmJit supports 7
434     //! segment registers - all addressable in both X86 and X64 modes and one
435     //! extra called `SReg::kIdNone`, which is AsmJit specific and means that
436     //! there is no segment register specified.
437     kIdCount = 7
438   };
439 };
440 
441 //! GPB low or high register (X86).
442 class Gpb : public Gp { ASMJIT_DEFINE_ABSTRACT_REG(Gpb, Gp) };
443 //! GPB low register (X86).
444 class GpbLo : public Gpb { ASMJIT_DEFINE_FINAL_REG(GpbLo, Gpb, RegTraits<kTypeGpbLo>) };
445 //! GPB high register (X86).
446 class GpbHi : public Gpb { ASMJIT_DEFINE_FINAL_REG(GpbHi, Gpb, RegTraits<kTypeGpbHi>) };
447 //! GPW register (X86).
448 class Gpw : public Gp { ASMJIT_DEFINE_FINAL_REG(Gpw, Gp, RegTraits<kTypeGpw>) };
449 //! GPD register (X86).
450 class Gpd : public Gp { ASMJIT_DEFINE_FINAL_REG(Gpd, Gp, RegTraits<kTypeGpd>) };
451 //! GPQ register (X86_64).
452 class Gpq : public Gp { ASMJIT_DEFINE_FINAL_REG(Gpq, Gp, RegTraits<kTypeGpq>) };
453 
454 //! 128-bit XMM register (SSE+).
455 class Xmm : public Vec {
ASMJIT_DEFINE_FINAL_REG(Xmm,Vec,RegTraits<kTypeXmm>)456   ASMJIT_DEFINE_FINAL_REG(Xmm, Vec, RegTraits<kTypeXmm>)
457   //! Casts this register to a register that has half the size (XMM).
458   inline Xmm half() const noexcept { return Xmm(id()); }
459 };
460 
461 //! 256-bit YMM register (AVX+).
462 class Ymm : public Vec {
ASMJIT_DEFINE_FINAL_REG(Ymm,Vec,RegTraits<kTypeYmm>)463   ASMJIT_DEFINE_FINAL_REG(Ymm, Vec, RegTraits<kTypeYmm>)
464   //! Casts this register to a register that has half the size (XMM).
465   inline Xmm half() const noexcept { return Xmm(id()); }
466 };
467 
468 //! 512-bit ZMM register (AVX512+).
469 class Zmm : public Vec {
ASMJIT_DEFINE_FINAL_REG(Zmm,Vec,RegTraits<kTypeZmm>)470   ASMJIT_DEFINE_FINAL_REG(Zmm, Vec, RegTraits<kTypeZmm>)
471   //! Casts this register to a register that has half the size (YMM).
472   inline Ymm half() const noexcept { return Ymm(id()); }
473 };
474 
475 //! 64-bit MMX register (MMX+).
476 class Mm : public Reg { ASMJIT_DEFINE_FINAL_REG(Mm, Reg, RegTraits<kTypeMm>) };
477 //! 64-bit K register (AVX512+).
478 class KReg : public Reg { ASMJIT_DEFINE_FINAL_REG(KReg, Reg, RegTraits<kTypeKReg>) };
479 //! 32-bit or 64-bit control register (X86).
480 class CReg : public Reg { ASMJIT_DEFINE_FINAL_REG(CReg, Reg, RegTraits<kTypeCReg>) };
481 //! 32-bit or 64-bit debug register (X86).
482 class DReg : public Reg { ASMJIT_DEFINE_FINAL_REG(DReg, Reg, RegTraits<kTypeDReg>) };
483 //! 80-bit FPU register (X86).
484 class St : public Reg { ASMJIT_DEFINE_FINAL_REG(St, Reg, RegTraits<kTypeSt>) };
485 //! 128-bit BND register (BND+).
486 class Bnd : public Reg { ASMJIT_DEFINE_FINAL_REG(Bnd, Reg, RegTraits<kTypeBnd>) };
487 //! 8192-bit TMM register (AMX).
488 class Tmm : public Reg { ASMJIT_DEFINE_FINAL_REG(Tmm, Reg, RegTraits<kTypeTmm>) };
489 //! RIP register (X86).
490 class Rip : public Reg { ASMJIT_DEFINE_FINAL_REG(Rip, Reg, RegTraits<kTypeRip>) };
491 
492 //! \cond
r8()493 inline GpbLo Gp::r8() const noexcept { return GpbLo(id()); }
r8Lo()494 inline GpbLo Gp::r8Lo() const noexcept { return GpbLo(id()); }
r8Hi()495 inline GpbHi Gp::r8Hi() const noexcept { return GpbHi(id()); }
r16()496 inline Gpw Gp::r16() const noexcept { return Gpw(id()); }
r32()497 inline Gpd Gp::r32() const noexcept { return Gpd(id()); }
r64()498 inline Gpq Gp::r64() const noexcept { return Gpq(id()); }
xmm()499 inline Xmm Vec::xmm() const noexcept { return Xmm(id()); }
ymm()500 inline Ymm Vec::ymm() const noexcept { return Ymm(id()); }
zmm()501 inline Zmm Vec::zmm() const noexcept { return Zmm(id()); }
502 //! \endcond
503 
504 //! \namespace asmjit::x86::regs
505 //!
506 //! Registers provided by X86 and X64 ISAs are in both `asmjit::x86` and
507 //! `asmjit::x86::regs` namespaces so they can be included with using directive.
508 //! For example `using namespace asmjit::x86::regs` would include all registers,
509 //! but not other X86-specific API, whereas `using namespace asmjit::x86` would
510 //! include everything X86-specific.
511 #ifndef _DOXYGEN
512 namespace regs {
513 #endif
514 
515 //! Creates an 8-bit low GPB register operand.
gpb(uint32_t rId)516 static constexpr GpbLo gpb(uint32_t rId) noexcept { return GpbLo(rId); }
517 //! Creates an 8-bit low GPB register operand.
gpb_lo(uint32_t rId)518 static constexpr GpbLo gpb_lo(uint32_t rId) noexcept { return GpbLo(rId); }
519 //! Creates an 8-bit high GPB register operand.
gpb_hi(uint32_t rId)520 static constexpr GpbHi gpb_hi(uint32_t rId) noexcept { return GpbHi(rId); }
521 //! Creates a 16-bit GPW register operand.
gpw(uint32_t rId)522 static constexpr Gpw gpw(uint32_t rId) noexcept { return Gpw(rId); }
523 //! Creates a 32-bit GPD register operand.
gpd(uint32_t rId)524 static constexpr Gpd gpd(uint32_t rId) noexcept { return Gpd(rId); }
525 //! Creates a 64-bit GPQ register operand (64-bit).
gpq(uint32_t rId)526 static constexpr Gpq gpq(uint32_t rId) noexcept { return Gpq(rId); }
527 //! Creates a 128-bit XMM register operand.
xmm(uint32_t rId)528 static constexpr Xmm xmm(uint32_t rId) noexcept { return Xmm(rId); }
529 //! Creates a 256-bit YMM register operand.
ymm(uint32_t rId)530 static constexpr Ymm ymm(uint32_t rId) noexcept { return Ymm(rId); }
531 //! Creates a 512-bit ZMM register operand.
zmm(uint32_t rId)532 static constexpr Zmm zmm(uint32_t rId) noexcept { return Zmm(rId); }
533 //! Creates a 64-bit Mm register operand.
mm(uint32_t rId)534 static constexpr Mm mm(uint32_t rId) noexcept { return Mm(rId); }
535 //! Creates a 64-bit K register operand.
k(uint32_t rId)536 static constexpr KReg k(uint32_t rId) noexcept { return KReg(rId); }
537 //! Creates a 32-bit or 64-bit control register operand.
cr(uint32_t rId)538 static constexpr CReg cr(uint32_t rId) noexcept { return CReg(rId); }
539 //! Creates a 32-bit or 64-bit debug register operand.
dr(uint32_t rId)540 static constexpr DReg dr(uint32_t rId) noexcept { return DReg(rId); }
541 //! Creates an 80-bit st register operand.
st(uint32_t rId)542 static constexpr St st(uint32_t rId) noexcept { return St(rId); }
543 //! Creates a 128-bit bound register operand.
bnd(uint32_t rId)544 static constexpr Bnd bnd(uint32_t rId) noexcept { return Bnd(rId); }
545 //! Creates a TMM register operand.
tmm(uint32_t rId)546 static constexpr Tmm tmm(uint32_t rId) noexcept { return Tmm(rId); }
547 
548 static constexpr GpbLo al = GpbLo(Gp::kIdAx);
549 static constexpr GpbLo bl = GpbLo(Gp::kIdBx);
550 static constexpr GpbLo cl = GpbLo(Gp::kIdCx);
551 static constexpr GpbLo dl = GpbLo(Gp::kIdDx);
552 static constexpr GpbLo spl = GpbLo(Gp::kIdSp);
553 static constexpr GpbLo bpl = GpbLo(Gp::kIdBp);
554 static constexpr GpbLo sil = GpbLo(Gp::kIdSi);
555 static constexpr GpbLo dil = GpbLo(Gp::kIdDi);
556 static constexpr GpbLo r8b = GpbLo(Gp::kIdR8);
557 static constexpr GpbLo r9b = GpbLo(Gp::kIdR9);
558 static constexpr GpbLo r10b = GpbLo(Gp::kIdR10);
559 static constexpr GpbLo r11b = GpbLo(Gp::kIdR11);
560 static constexpr GpbLo r12b = GpbLo(Gp::kIdR12);
561 static constexpr GpbLo r13b = GpbLo(Gp::kIdR13);
562 static constexpr GpbLo r14b = GpbLo(Gp::kIdR14);
563 static constexpr GpbLo r15b = GpbLo(Gp::kIdR15);
564 
565 static constexpr GpbHi ah = GpbHi(Gp::kIdAx);
566 static constexpr GpbHi bh = GpbHi(Gp::kIdBx);
567 static constexpr GpbHi ch = GpbHi(Gp::kIdCx);
568 static constexpr GpbHi dh = GpbHi(Gp::kIdDx);
569 
570 static constexpr Gpw ax = Gpw(Gp::kIdAx);
571 static constexpr Gpw bx = Gpw(Gp::kIdBx);
572 static constexpr Gpw cx = Gpw(Gp::kIdCx);
573 static constexpr Gpw dx = Gpw(Gp::kIdDx);
574 static constexpr Gpw sp = Gpw(Gp::kIdSp);
575 static constexpr Gpw bp = Gpw(Gp::kIdBp);
576 static constexpr Gpw si = Gpw(Gp::kIdSi);
577 static constexpr Gpw di = Gpw(Gp::kIdDi);
578 static constexpr Gpw r8w = Gpw(Gp::kIdR8);
579 static constexpr Gpw r9w = Gpw(Gp::kIdR9);
580 static constexpr Gpw r10w = Gpw(Gp::kIdR10);
581 static constexpr Gpw r11w = Gpw(Gp::kIdR11);
582 static constexpr Gpw r12w = Gpw(Gp::kIdR12);
583 static constexpr Gpw r13w = Gpw(Gp::kIdR13);
584 static constexpr Gpw r14w = Gpw(Gp::kIdR14);
585 static constexpr Gpw r15w = Gpw(Gp::kIdR15);
586 
587 static constexpr Gpd eax = Gpd(Gp::kIdAx);
588 static constexpr Gpd ebx = Gpd(Gp::kIdBx);
589 static constexpr Gpd ecx = Gpd(Gp::kIdCx);
590 static constexpr Gpd edx = Gpd(Gp::kIdDx);
591 static constexpr Gpd esp = Gpd(Gp::kIdSp);
592 static constexpr Gpd ebp = Gpd(Gp::kIdBp);
593 static constexpr Gpd esi = Gpd(Gp::kIdSi);
594 static constexpr Gpd edi = Gpd(Gp::kIdDi);
595 static constexpr Gpd r8d = Gpd(Gp::kIdR8);
596 static constexpr Gpd r9d = Gpd(Gp::kIdR9);
597 static constexpr Gpd r10d = Gpd(Gp::kIdR10);
598 static constexpr Gpd r11d = Gpd(Gp::kIdR11);
599 static constexpr Gpd r12d = Gpd(Gp::kIdR12);
600 static constexpr Gpd r13d = Gpd(Gp::kIdR13);
601 static constexpr Gpd r14d = Gpd(Gp::kIdR14);
602 static constexpr Gpd r15d = Gpd(Gp::kIdR15);
603 
604 static constexpr Gpq rax = Gpq(Gp::kIdAx);
605 static constexpr Gpq rbx = Gpq(Gp::kIdBx);
606 static constexpr Gpq rcx = Gpq(Gp::kIdCx);
607 static constexpr Gpq rdx = Gpq(Gp::kIdDx);
608 static constexpr Gpq rsp = Gpq(Gp::kIdSp);
609 static constexpr Gpq rbp = Gpq(Gp::kIdBp);
610 static constexpr Gpq rsi = Gpq(Gp::kIdSi);
611 static constexpr Gpq rdi = Gpq(Gp::kIdDi);
612 static constexpr Gpq r8 = Gpq(Gp::kIdR8);
613 static constexpr Gpq r9 = Gpq(Gp::kIdR9);
614 static constexpr Gpq r10 = Gpq(Gp::kIdR10);
615 static constexpr Gpq r11 = Gpq(Gp::kIdR11);
616 static constexpr Gpq r12 = Gpq(Gp::kIdR12);
617 static constexpr Gpq r13 = Gpq(Gp::kIdR13);
618 static constexpr Gpq r14 = Gpq(Gp::kIdR14);
619 static constexpr Gpq r15 = Gpq(Gp::kIdR15);
620 
621 static constexpr Xmm xmm0 = Xmm(0);
622 static constexpr Xmm xmm1 = Xmm(1);
623 static constexpr Xmm xmm2 = Xmm(2);
624 static constexpr Xmm xmm3 = Xmm(3);
625 static constexpr Xmm xmm4 = Xmm(4);
626 static constexpr Xmm xmm5 = Xmm(5);
627 static constexpr Xmm xmm6 = Xmm(6);
628 static constexpr Xmm xmm7 = Xmm(7);
629 static constexpr Xmm xmm8 = Xmm(8);
630 static constexpr Xmm xmm9 = Xmm(9);
631 static constexpr Xmm xmm10 = Xmm(10);
632 static constexpr Xmm xmm11 = Xmm(11);
633 static constexpr Xmm xmm12 = Xmm(12);
634 static constexpr Xmm xmm13 = Xmm(13);
635 static constexpr Xmm xmm14 = Xmm(14);
636 static constexpr Xmm xmm15 = Xmm(15);
637 static constexpr Xmm xmm16 = Xmm(16);
638 static constexpr Xmm xmm17 = Xmm(17);
639 static constexpr Xmm xmm18 = Xmm(18);
640 static constexpr Xmm xmm19 = Xmm(19);
641 static constexpr Xmm xmm20 = Xmm(20);
642 static constexpr Xmm xmm21 = Xmm(21);
643 static constexpr Xmm xmm22 = Xmm(22);
644 static constexpr Xmm xmm23 = Xmm(23);
645 static constexpr Xmm xmm24 = Xmm(24);
646 static constexpr Xmm xmm25 = Xmm(25);
647 static constexpr Xmm xmm26 = Xmm(26);
648 static constexpr Xmm xmm27 = Xmm(27);
649 static constexpr Xmm xmm28 = Xmm(28);
650 static constexpr Xmm xmm29 = Xmm(29);
651 static constexpr Xmm xmm30 = Xmm(30);
652 static constexpr Xmm xmm31 = Xmm(31);
653 
654 static constexpr Ymm ymm0 = Ymm(0);
655 static constexpr Ymm ymm1 = Ymm(1);
656 static constexpr Ymm ymm2 = Ymm(2);
657 static constexpr Ymm ymm3 = Ymm(3);
658 static constexpr Ymm ymm4 = Ymm(4);
659 static constexpr Ymm ymm5 = Ymm(5);
660 static constexpr Ymm ymm6 = Ymm(6);
661 static constexpr Ymm ymm7 = Ymm(7);
662 static constexpr Ymm ymm8 = Ymm(8);
663 static constexpr Ymm ymm9 = Ymm(9);
664 static constexpr Ymm ymm10 = Ymm(10);
665 static constexpr Ymm ymm11 = Ymm(11);
666 static constexpr Ymm ymm12 = Ymm(12);
667 static constexpr Ymm ymm13 = Ymm(13);
668 static constexpr Ymm ymm14 = Ymm(14);
669 static constexpr Ymm ymm15 = Ymm(15);
670 static constexpr Ymm ymm16 = Ymm(16);
671 static constexpr Ymm ymm17 = Ymm(17);
672 static constexpr Ymm ymm18 = Ymm(18);
673 static constexpr Ymm ymm19 = Ymm(19);
674 static constexpr Ymm ymm20 = Ymm(20);
675 static constexpr Ymm ymm21 = Ymm(21);
676 static constexpr Ymm ymm22 = Ymm(22);
677 static constexpr Ymm ymm23 = Ymm(23);
678 static constexpr Ymm ymm24 = Ymm(24);
679 static constexpr Ymm ymm25 = Ymm(25);
680 static constexpr Ymm ymm26 = Ymm(26);
681 static constexpr Ymm ymm27 = Ymm(27);
682 static constexpr Ymm ymm28 = Ymm(28);
683 static constexpr Ymm ymm29 = Ymm(29);
684 static constexpr Ymm ymm30 = Ymm(30);
685 static constexpr Ymm ymm31 = Ymm(31);
686 
687 static constexpr Zmm zmm0 = Zmm(0);
688 static constexpr Zmm zmm1 = Zmm(1);
689 static constexpr Zmm zmm2 = Zmm(2);
690 static constexpr Zmm zmm3 = Zmm(3);
691 static constexpr Zmm zmm4 = Zmm(4);
692 static constexpr Zmm zmm5 = Zmm(5);
693 static constexpr Zmm zmm6 = Zmm(6);
694 static constexpr Zmm zmm7 = Zmm(7);
695 static constexpr Zmm zmm8 = Zmm(8);
696 static constexpr Zmm zmm9 = Zmm(9);
697 static constexpr Zmm zmm10 = Zmm(10);
698 static constexpr Zmm zmm11 = Zmm(11);
699 static constexpr Zmm zmm12 = Zmm(12);
700 static constexpr Zmm zmm13 = Zmm(13);
701 static constexpr Zmm zmm14 = Zmm(14);
702 static constexpr Zmm zmm15 = Zmm(15);
703 static constexpr Zmm zmm16 = Zmm(16);
704 static constexpr Zmm zmm17 = Zmm(17);
705 static constexpr Zmm zmm18 = Zmm(18);
706 static constexpr Zmm zmm19 = Zmm(19);
707 static constexpr Zmm zmm20 = Zmm(20);
708 static constexpr Zmm zmm21 = Zmm(21);
709 static constexpr Zmm zmm22 = Zmm(22);
710 static constexpr Zmm zmm23 = Zmm(23);
711 static constexpr Zmm zmm24 = Zmm(24);
712 static constexpr Zmm zmm25 = Zmm(25);
713 static constexpr Zmm zmm26 = Zmm(26);
714 static constexpr Zmm zmm27 = Zmm(27);
715 static constexpr Zmm zmm28 = Zmm(28);
716 static constexpr Zmm zmm29 = Zmm(29);
717 static constexpr Zmm zmm30 = Zmm(30);
718 static constexpr Zmm zmm31 = Zmm(31);
719 
720 static constexpr Mm mm0 = Mm(0);
721 static constexpr Mm mm1 = Mm(1);
722 static constexpr Mm mm2 = Mm(2);
723 static constexpr Mm mm3 = Mm(3);
724 static constexpr Mm mm4 = Mm(4);
725 static constexpr Mm mm5 = Mm(5);
726 static constexpr Mm mm6 = Mm(6);
727 static constexpr Mm mm7 = Mm(7);
728 
729 static constexpr KReg k0 = KReg(0);
730 static constexpr KReg k1 = KReg(1);
731 static constexpr KReg k2 = KReg(2);
732 static constexpr KReg k3 = KReg(3);
733 static constexpr KReg k4 = KReg(4);
734 static constexpr KReg k5 = KReg(5);
735 static constexpr KReg k6 = KReg(6);
736 static constexpr KReg k7 = KReg(7);
737 
738 static constexpr SReg no_seg = SReg(SReg::kIdNone);
739 static constexpr SReg es = SReg(SReg::kIdEs);
740 static constexpr SReg cs = SReg(SReg::kIdCs);
741 static constexpr SReg ss = SReg(SReg::kIdSs);
742 static constexpr SReg ds = SReg(SReg::kIdDs);
743 static constexpr SReg fs = SReg(SReg::kIdFs);
744 static constexpr SReg gs = SReg(SReg::kIdGs);
745 
746 static constexpr CReg cr0 = CReg(0);
747 static constexpr CReg cr1 = CReg(1);
748 static constexpr CReg cr2 = CReg(2);
749 static constexpr CReg cr3 = CReg(3);
750 static constexpr CReg cr4 = CReg(4);
751 static constexpr CReg cr5 = CReg(5);
752 static constexpr CReg cr6 = CReg(6);
753 static constexpr CReg cr7 = CReg(7);
754 static constexpr CReg cr8 = CReg(8);
755 static constexpr CReg cr9 = CReg(9);
756 static constexpr CReg cr10 = CReg(10);
757 static constexpr CReg cr11 = CReg(11);
758 static constexpr CReg cr12 = CReg(12);
759 static constexpr CReg cr13 = CReg(13);
760 static constexpr CReg cr14 = CReg(14);
761 static constexpr CReg cr15 = CReg(15);
762 
763 static constexpr DReg dr0 = DReg(0);
764 static constexpr DReg dr1 = DReg(1);
765 static constexpr DReg dr2 = DReg(2);
766 static constexpr DReg dr3 = DReg(3);
767 static constexpr DReg dr4 = DReg(4);
768 static constexpr DReg dr5 = DReg(5);
769 static constexpr DReg dr6 = DReg(6);
770 static constexpr DReg dr7 = DReg(7);
771 static constexpr DReg dr8 = DReg(8);
772 static constexpr DReg dr9 = DReg(9);
773 static constexpr DReg dr10 = DReg(10);
774 static constexpr DReg dr11 = DReg(11);
775 static constexpr DReg dr12 = DReg(12);
776 static constexpr DReg dr13 = DReg(13);
777 static constexpr DReg dr14 = DReg(14);
778 static constexpr DReg dr15 = DReg(15);
779 
780 static constexpr St st0 = St(0);
781 static constexpr St st1 = St(1);
782 static constexpr St st2 = St(2);
783 static constexpr St st3 = St(3);
784 static constexpr St st4 = St(4);
785 static constexpr St st5 = St(5);
786 static constexpr St st6 = St(6);
787 static constexpr St st7 = St(7);
788 
789 static constexpr Bnd bnd0 = Bnd(0);
790 static constexpr Bnd bnd1 = Bnd(1);
791 static constexpr Bnd bnd2 = Bnd(2);
792 static constexpr Bnd bnd3 = Bnd(3);
793 
794 static constexpr Tmm tmm0 = Tmm(0);
795 static constexpr Tmm tmm1 = Tmm(1);
796 static constexpr Tmm tmm2 = Tmm(2);
797 static constexpr Tmm tmm3 = Tmm(3);
798 static constexpr Tmm tmm4 = Tmm(4);
799 static constexpr Tmm tmm5 = Tmm(5);
800 static constexpr Tmm tmm6 = Tmm(6);
801 static constexpr Tmm tmm7 = Tmm(7);
802 
803 static constexpr Rip rip = Rip(0);
804 
805 #ifndef _DOXYGEN
806 } // {regs}
807 
808 // Make `x86::regs` accessible through `x86` namespace as well.
809 using namespace regs;
810 #endif
811 
812 // ============================================================================
813 // [asmjit::x86::Mem]
814 // ============================================================================
815 
816 //! Memory operand.
817 class Mem : public BaseMem {
818 public:
819   //! Additional bits of operand's signature used by `x86::Mem`.
820   enum AdditionalBits : uint32_t {
821     // Memory address type (2 bits).
822     // |........|........|XX......|........|
823     kSignatureMemAddrTypeShift = 14,
824     kSignatureMemAddrTypeMask = 0x03u << kSignatureMemAddrTypeShift,
825 
826     // Memory shift amount (2 bits).
827     // |........|......XX|........|........|
828     kSignatureMemShiftValueShift = 16,
829     kSignatureMemShiftValueMask = 0x03u << kSignatureMemShiftValueShift,
830 
831     // Memory segment reg (3 bits).
832     // |........|...XXX..|........|........|
833     kSignatureMemSegmentShift = 18,
834     kSignatureMemSegmentMask = 0x07u << kSignatureMemSegmentShift,
835 
836     // Memory broadcast type (3 bits).
837     // |........|XXX.....|........|........|
838     kSignatureMemBroadcastShift = 21,
839     kSignatureMemBroadcastMask = 0x7u << kSignatureMemBroadcastShift
840   };
841 
842   //! Address type.
843   enum AddrType : uint32_t {
844     //! Default address type, Assembler will select the best type when necessary.
845     kAddrTypeDefault = 0,
846     //! Absolute address type.
847     kAddrTypeAbs = 1,
848     //! Relative address type.
849     kAddrTypeRel = 2
850   };
851 
852   //! Memory broadcast type.
853   enum Broadcast : uint32_t {
854     //! Broadcast {1to1}.
855     kBroadcast1To1 = 0,
856     //! Broadcast {1to2}.
857     kBroadcast1To2 = 1,
858     //! Broadcast {1to4}.
859     kBroadcast1To4 = 2,
860     //! Broadcast {1to8}.
861     kBroadcast1To8 = 3,
862     //! Broadcast {1to16}.
863     kBroadcast1To16 = 4,
864     //! Broadcast {1to32}.
865     kBroadcast1To32 = 5,
866     //! Broadcast {1to64}.
867     kBroadcast1To64 = 6
868   };
869 
870   //! \cond
871   //! Shortcuts.
872   enum SignatureMem : uint32_t {
873     kSignatureMemAbs = kAddrTypeAbs << kSignatureMemAddrTypeShift,
874     kSignatureMemRel = kAddrTypeRel << kSignatureMemAddrTypeShift
875   };
876   //! \endcond
877 
878   // --------------------------------------------------------------------------
879   // [Construction / Destruction]
880   // --------------------------------------------------------------------------
881 
882   //! Creates a default `Mem` operand that points to [0].
Mem()883   constexpr Mem() noexcept
884     : BaseMem() {}
885 
Mem(const Mem & other)886   constexpr Mem(const Mem& other) noexcept
887     : BaseMem(other) {}
888 
889   //! \cond INTERNAL
890   //!
891   //! A constructor used internally to create `Mem` operand from `Decomposed` data.
Mem(const Decomposed & d)892   constexpr explicit Mem(const Decomposed& d) noexcept
893     : BaseMem(d) {}
894   //! \endcond
895 
896   constexpr Mem(const Label& base, int32_t off, uint32_t size = 0, uint32_t flags = 0) noexcept
BaseMem(Decomposed{ Label::kLabelTag, base.id(), 0, 0, off, size, flags })897     : BaseMem(Decomposed { Label::kLabelTag, base.id(), 0, 0, off, size, flags }) {}
898 
899   constexpr Mem(const Label& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, uint32_t flags = 0) noexcept
BaseMem(Decomposed{ Label::kLabelTag, base.id(), index.type(), index.id(), off, size, flags | (shift << kSignatureMemShiftValueShift) })900     : BaseMem(Decomposed { Label::kLabelTag, base.id(), index.type(), index.id(), off, size, flags | (shift << kSignatureMemShiftValueShift) }) {}
901 
902   constexpr Mem(const BaseReg& base, int32_t off, uint32_t size = 0, uint32_t flags = 0) noexcept
BaseMem(Decomposed{ base.type(), base.id(), 0, 0, off, size, flags })903     : BaseMem(Decomposed { base.type(), base.id(), 0, 0, off, size, flags }) {}
904 
905   constexpr Mem(const BaseReg& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, uint32_t flags = 0) noexcept
BaseMem(Decomposed{ base.type(), base.id(), index.type(), index.id(), off, size, flags | (shift << kSignatureMemShiftValueShift) })906     : BaseMem(Decomposed { base.type(), base.id(), index.type(), index.id(), off, size, flags | (shift << kSignatureMemShiftValueShift) }) {}
907 
908   constexpr explicit Mem(uint64_t base, uint32_t size = 0, uint32_t flags = 0) noexcept
BaseMem(Decomposed{ 0, uint32_t(base >> 32), 0, 0, int32_t(uint32_t(base & 0xFFFFFFFFu)), size, flags })909     : BaseMem(Decomposed { 0, uint32_t(base >> 32), 0, 0, int32_t(uint32_t(base & 0xFFFFFFFFu)), size, flags }) {}
910 
911   constexpr Mem(uint64_t base, const BaseReg& index, uint32_t shift = 0, uint32_t size = 0, uint32_t flags = 0) noexcept
BaseMem(Decomposed{ 0, uint32_t(base >> 32), index.type(), index.id(), int32_t(uint32_t(base & 0xFFFFFFFFu)), size, flags | (shift << kSignatureMemShiftValueShift) })912     : BaseMem(Decomposed { 0, uint32_t(base >> 32), index.type(), index.id(), int32_t(uint32_t(base & 0xFFFFFFFFu)), size, flags | (shift << kSignatureMemShiftValueShift) }) {}
913 
Mem(Globals::Init_,uint32_t u0,uint32_t u1,uint32_t u2,uint32_t u3)914   constexpr Mem(Globals::Init_, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3) noexcept
915     : BaseMem(Globals::Init, u0, u1, u2, u3) {}
916 
Mem(Globals::NoInit_)917   inline explicit Mem(Globals::NoInit_) noexcept
918     : BaseMem(Globals::NoInit) {}
919 
920   //! Clones the memory operand.
clone()921   constexpr Mem clone() const noexcept { return Mem(*this); }
922 
923   //! Creates a new copy of this memory operand adjusted by `off`.
cloneAdjusted(int64_t off)924   inline Mem cloneAdjusted(int64_t off) const noexcept {
925     Mem result(*this);
926     result.addOffset(off);
927     return result;
928   }
929 
930   //! Converts memory `baseType` and `baseId` to `x86::Reg` instance.
931   //!
932   //! The memory must have a valid base register otherwise the result will be wrong.
baseReg()933   inline Reg baseReg() const noexcept { return Reg::fromTypeAndId(baseType(), baseId()); }
934 
935   //! Converts memory `indexType` and `indexId` to `x86::Reg` instance.
936   //!
937   //! The memory must have a valid index register otherwise the result will be wrong.
indexReg()938   inline Reg indexReg() const noexcept { return Reg::fromTypeAndId(indexType(), indexId()); }
939 
_1to1()940   constexpr Mem _1to1() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To1 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); }
_1to2()941   constexpr Mem _1to2() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To2 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); }
_1to4()942   constexpr Mem _1to4() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To4 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); }
_1to8()943   constexpr Mem _1to8() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To8 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); }
_1to16()944   constexpr Mem _1to16() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To16 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); }
_1to32()945   constexpr Mem _1to32() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To32 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); }
_1to64()946   constexpr Mem _1to64() const noexcept { return Mem(Globals::Init, (_signature & ~kSignatureMemBroadcastMask) | (kBroadcast1To64 << kSignatureMemBroadcastShift), _baseId, _data[0], _data[1]); }
947 
948   // --------------------------------------------------------------------------
949   // [Mem]
950   // --------------------------------------------------------------------------
951 
952   using BaseMem::setIndex;
953 
setIndex(const BaseReg & index,uint32_t shift)954   inline void setIndex(const BaseReg& index, uint32_t shift) noexcept {
955     setIndex(index);
956     setShift(shift);
957   }
958 
959   //! Returns the address type (see \ref AddrType) of the memory operand.
960   //!
961   //! By default, address type of newly created memory operands is always \ref kAddrTypeDefault.
addrType()962   constexpr uint32_t addrType() const noexcept { return _getSignaturePart<kSignatureMemAddrTypeMask>(); }
963   //! Sets the address type to `addrType`, see \ref AddrType.
setAddrType(uint32_t addrType)964   inline void setAddrType(uint32_t addrType) noexcept { _setSignaturePart<kSignatureMemAddrTypeMask>(addrType); }
965   //! Resets the address type to \ref kAddrTypeDefault.
resetAddrType()966   inline void resetAddrType() noexcept { _setSignaturePart<kSignatureMemAddrTypeMask>(0); }
967 
968   //! Tests whether the address type is \ref kAddrTypeAbs.
isAbs()969   constexpr bool isAbs() const noexcept { return addrType() == kAddrTypeAbs; }
970   //! Sets the address type to \ref kAddrTypeAbs.
setAbs()971   inline void setAbs() noexcept { setAddrType(kAddrTypeAbs); }
972 
973   //! Tests whether the address type is \ref kAddrTypeRel.
isRel()974   constexpr bool isRel() const noexcept { return addrType() == kAddrTypeRel; }
975   //! Sets the address type to \ref kAddrTypeRel.
setRel()976   inline void setRel() noexcept { setAddrType(kAddrTypeRel); }
977 
978   //! Tests whether the memory operand has a segment override.
hasSegment()979   constexpr bool hasSegment() const noexcept { return _hasSignaturePart<kSignatureMemSegmentMask>(); }
980   //! Returns the associated segment override as `SReg` operand.
segment()981   constexpr SReg segment() const noexcept { return SReg(segmentId()); }
982   //! Returns segment override register id, see `SReg::Id`.
segmentId()983   constexpr uint32_t segmentId() const noexcept { return _getSignaturePart<kSignatureMemSegmentMask>(); }
984 
985   //! Sets the segment override to `seg`.
setSegment(const SReg & seg)986   inline void setSegment(const SReg& seg) noexcept { setSegment(seg.id()); }
987   //! Sets the segment override to `id`.
setSegment(uint32_t rId)988   inline void setSegment(uint32_t rId) noexcept { _setSignaturePart<kSignatureMemSegmentMask>(rId); }
989   //! Resets the segment override.
resetSegment()990   inline void resetSegment() noexcept { _setSignaturePart<kSignatureMemSegmentMask>(0); }
991 
992   //! Tests whether the memory operand has shift (aka scale) value.
hasShift()993   constexpr bool hasShift() const noexcept { return _hasSignaturePart<kSignatureMemShiftValueMask>(); }
994   //! Returns the memory operand's shift (aka scale) value.
shift()995   constexpr uint32_t shift() const noexcept { return _getSignaturePart<kSignatureMemShiftValueMask>(); }
996   //! Sets the memory operand's shift (aka scale) value.
setShift(uint32_t shift)997   inline void setShift(uint32_t shift) noexcept { _setSignaturePart<kSignatureMemShiftValueMask>(shift); }
998   //! Resets the memory operand's shift (aka scale) value to zero.
resetShift()999   inline void resetShift() noexcept { _setSignaturePart<kSignatureMemShiftValueMask>(0); }
1000 
1001   //! Tests whether the memory operand has broadcast {1tox}.
hasBroadcast()1002   constexpr bool hasBroadcast() const noexcept { return _hasSignaturePart<kSignatureMemBroadcastMask>(); }
1003   //! Returns the memory operand's broadcast.
getBroadcast()1004   constexpr uint32_t getBroadcast() const noexcept { return _getSignaturePart<kSignatureMemBroadcastMask>(); }
1005   //! Sets the memory operand's broadcast.
setBroadcast(uint32_t bcst)1006   inline void setBroadcast(uint32_t bcst) noexcept { _setSignaturePart<kSignatureMemBroadcastMask>(bcst); }
1007   //! Resets the memory operand's broadcast to none.
resetBroadcast()1008   inline void resetBroadcast() noexcept { _setSignaturePart<kSignatureMemBroadcastMask>(0); }
1009 
1010   // --------------------------------------------------------------------------
1011   // [Operator Overload]
1012   // --------------------------------------------------------------------------
1013 
1014   inline Mem& operator=(const Mem& other) noexcept = default;
1015 };
1016 
1017 //! Creates `[base.reg + offset]` memory operand.
1018 static constexpr Mem ptr(const Gp& base, int32_t offset = 0, uint32_t size = 0) noexcept {
1019   return Mem(base, offset, size);
1020 }
1021 //! Creates `[base.reg + (index << shift) + offset]` memory operand (scalar index).
1022 static constexpr Mem ptr(const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept {
1023   return Mem(base, index, shift, offset, size);
1024 }
1025 //! Creates `[base.reg + (index << shift) + offset]` memory operand (vector index).
1026 static constexpr Mem ptr(const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept {
1027   return Mem(base, index, shift, offset, size);
1028 }
1029 
1030 //! Creates `[base + offset]` memory operand.
1031 static constexpr Mem ptr(const Label& base, int32_t offset = 0, uint32_t size = 0) noexcept {
1032   return Mem(base, offset, size);
1033 }
1034 //! Creates `[base + (index << shift) + offset]` memory operand.
1035 static constexpr Mem ptr(const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept {
1036   return Mem(base, index, shift, offset, size);
1037 }
1038 //! Creates `[base + (index << shift) + offset]` memory operand.
1039 static constexpr Mem ptr(const Label& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept {
1040   return Mem(base, index, shift, offset, size);
1041 }
1042 
1043 //! Creates `[rip + offset]` memory operand.
1044 static constexpr Mem ptr(const Rip& rip_, int32_t offset = 0, uint32_t size = 0) noexcept {
1045   return Mem(rip_, offset, size);
1046 }
1047 
1048 //! Creates `[base]` absolute memory operand.
1049 static constexpr Mem ptr(uint64_t base, uint32_t size = 0) noexcept {
1050   return Mem(base, size);
1051 }
1052 //! Creates `[base + (index.reg << shift)]` absolute memory operand.
1053 static constexpr Mem ptr(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
1054   return Mem(base, index, shift, size);
1055 }
1056 //! Creates `[base + (index.reg << shift)]` absolute memory operand.
1057 static constexpr Mem ptr(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
1058   return Mem(base, index, shift, size);
1059 }
1060 
1061 //! Creates `[base]` absolute memory operand (absolute).
1062 static constexpr Mem ptr_abs(uint64_t base, uint32_t size = 0) noexcept {
1063   return Mem(base, size, Mem::kSignatureMemAbs);
1064 }
1065 //! Creates `[base + (index.reg << shift)]` absolute memory operand (absolute).
1066 static constexpr Mem ptr_abs(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
1067   return Mem(base, index, shift, size, Mem::kSignatureMemAbs);
1068 }
1069 //! Creates `[base + (index.reg << shift)]` absolute memory operand (absolute).
1070 static constexpr Mem ptr_abs(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
1071   return Mem(base, index, shift, size, Mem::kSignatureMemAbs);
1072 }
1073 
1074 //! Creates `[base]` relative memory operand (relative).
1075 static constexpr Mem ptr_rel(uint64_t base, uint32_t size = 0) noexcept {
1076   return Mem(base, size, Mem::kSignatureMemRel);
1077 }
1078 //! Creates `[base + (index.reg << shift)]` relative memory operand (relative).
1079 static constexpr Mem ptr_rel(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
1080   return Mem(base, index, shift, size, Mem::kSignatureMemRel);
1081 }
1082 //! Creates `[base + (index.reg << shift)]` relative memory operand (relative).
1083 static constexpr Mem ptr_rel(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
1084   return Mem(base, index, shift, size, Mem::kSignatureMemRel);
1085 }
1086 
1087 // Definition of memory operand constructors that use platform independent naming.
1088 ASMJIT_MEM_PTR(ptr_8, 1)
1089 ASMJIT_MEM_PTR(ptr_16, 2)
1090 ASMJIT_MEM_PTR(ptr_32, 4)
1091 ASMJIT_MEM_PTR(ptr_48, 6)
1092 ASMJIT_MEM_PTR(ptr_64, 8)
1093 ASMJIT_MEM_PTR(ptr_80, 10)
1094 ASMJIT_MEM_PTR(ptr_128, 16)
1095 ASMJIT_MEM_PTR(ptr_256, 32)
1096 ASMJIT_MEM_PTR(ptr_512, 64)
1097 
1098 // Definition of memory operand constructors that use X86-specific convention.
1099 ASMJIT_MEM_PTR(byte_ptr, 1)
1100 ASMJIT_MEM_PTR(word_ptr, 2)
1101 ASMJIT_MEM_PTR(dword_ptr, 4)
1102 ASMJIT_MEM_PTR(fword_ptr, 6)
1103 ASMJIT_MEM_PTR(qword_ptr, 8)
1104 ASMJIT_MEM_PTR(tbyte_ptr, 10)
1105 ASMJIT_MEM_PTR(tword_ptr, 10)
1106 ASMJIT_MEM_PTR(oword_ptr, 16)
1107 ASMJIT_MEM_PTR(dqword_ptr, 16)
1108 ASMJIT_MEM_PTR(qqword_ptr, 32)
1109 ASMJIT_MEM_PTR(xmmword_ptr, 16)
1110 ASMJIT_MEM_PTR(ymmword_ptr, 32)
1111 ASMJIT_MEM_PTR(zmmword_ptr, 64)
1112 
1113 //! \}
1114 
1115 ASMJIT_END_SUB_NAMESPACE
1116 
1117 // ============================================================================
1118 // [asmjit::Type::IdOfT<x86::Reg>]
1119 // ============================================================================
1120 
1121 //! \cond INTERNAL
1122 ASMJIT_BEGIN_NAMESPACE
1123 ASMJIT_DEFINE_TYPE_ID(x86::Gpb, kIdI8);
1124 ASMJIT_DEFINE_TYPE_ID(x86::Gpw, kIdI16);
1125 ASMJIT_DEFINE_TYPE_ID(x86::Gpd, kIdI32);
1126 ASMJIT_DEFINE_TYPE_ID(x86::Gpq, kIdI64);
1127 ASMJIT_DEFINE_TYPE_ID(x86::Mm , kIdMmx64);
1128 ASMJIT_DEFINE_TYPE_ID(x86::Xmm, kIdI32x4);
1129 ASMJIT_DEFINE_TYPE_ID(x86::Ymm, kIdI32x8);
1130 ASMJIT_DEFINE_TYPE_ID(x86::Zmm, kIdI32x16);
1131 ASMJIT_END_NAMESPACE
1132 //! \endcond
1133 
1134 #undef ASMJIT_MEM_PTR
1135 
1136 #endif // ASMJIT_X86_X86OPERAND_H_INCLUDED
1137