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