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