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_X86OPCODE_P_H_INCLUDED
8 : #define ASMJIT_X86_X86OPCODE_P_H_INCLUDED
9 :
10 : #include "x86globals.h"
11 :
12 : ASMJIT_BEGIN_SUB_NAMESPACE(x86)
13 :
14 : //! \cond INTERNAL
15 : //! \addtogroup asmjit_x86
16 : //! \{
17 :
18 : //! Helper class to store and manipulate X86 opcodes.
19 : //!
20 : //! The first 8 least significant bits describe the opcode byte as defined in ISA manuals, all other bits
21 : //! describe other properties like prefixes, see `Opcode::Bits` for more information.
22 : struct Opcode {
23 : uint32_t v;
24 :
25 : //! Describes a meaning of all bits of AsmJit's 32-bit opcode value.
26 : //!
27 : //! This schema is AsmJit specific and has been designed to allow encoding of all X86 instructions available. X86,
28 : //! MMX, and SSE+ instructions always use `MM` and `PP` fields, which are encoded to corresponding prefixes needed
29 : //! by X86 or SIMD instructions. AVX+ instructions embed `MMMMM` and `PP` fields in a VEX prefix, and AVX-512
30 : //! instructions embed `MM` and `PP` in EVEX prefix.
31 : //!
32 : //! The instruction opcode definition uses 1 or 2 bytes as an opcode value. 1 byte is needed by most of the
33 : //! instructions, 2 bytes are only used by legacy X87-FPU instructions. This means that a second byte is free to
34 : //! by used by instructions encoded by using VEX and/or EVEX prefix.
35 : //!
36 : //! The fields description:
37 : //!
38 : //! - `MM` field is used to encode prefixes needed by the instruction or as a part of VEX/EVEX prefix. Described as
39 : //! `mm` and `mmmmm` in instruction manuals.
40 : //!
41 : //! NOTE: Since `MM` field is defined as `mmmmm` (5 bits), but only 2 least significant bits are used by VEX and
42 : //! EVEX prefixes, and additional 4th bit is used by XOP prefix, AsmJit uses the 3rd and 5th bit for it's own
43 : //! purposes. These bits will probably never be used in future encodings as AVX512 uses only `000mm` from `mmmmm`.
44 : //!
45 : //! - `PP` field is used to encode prefixes needed by the instruction or as a part of VEX/EVEX prefix. Described as
46 : //! `pp` in instruction manuals.
47 : //!
48 : //! - `LL` field is used exclusively by AVX+ and AVX512+ instruction sets. It describes vector size, which is `L.128`
49 : //! for XMM register, `L.256` for for YMM register, and `L.512` for ZMM register. The `LL` field is omitted in case
50 : //! that instruction supports multiple vector lengths, however, if the instruction requires specific `L` value it
51 : //! must be specified as a part of the opcode.
52 : //!
53 : //! NOTE: `LL` having value `11` is not defined yet.
54 : //!
55 : //! - `W` field is the most complicated. It was added by 64-bit architecture to promote default operation width
56 : //! (instructions that perform 32-bit operation by default require to override the width to 64-bit explicitly).
57 : //! There is nothing wrong on this, however, some instructions introduced implicit `W` override, for example a
58 : //! `cdqe` instruction is basically a `cwde` instruction with overridden `W` (set to 1). There are some others
59 : //! in the base X86 instruction set. More recent instruction sets started using `W` field more often:
60 : //!
61 : //! - AVX instructions started using `W` field as an extended opcode for FMA, GATHER, PERM, and other instructions.
62 : //! It also uses `W` field to override the default operation width in instructions like `vmovq`.
63 : //!
64 : //! - AVX-512 instructions started using `W` field as an extended opcode for all new instructions. This wouldn't
65 : //! have been an issue if the `W` field of AVX-512 have matched AVX, but this is not always the case.
66 : //!
67 : //! - `O` field is an extended opcode field (3 bits) embedded in ModR/M BYTE.
68 : //!
69 : //! - `CDSHL` and `CDTT` fields describe 'compressed-displacement'. `CDSHL` is defined for each instruction that is
70 : //! AVX-512 encodable (EVEX) and contains a base N shift (base shift to perform the calculation). The `CDTT` field
71 : //! is derived from instruction specification and describes additional shift to calculate the final `CDSHL` that
72 : //! will be used in SIB byte.
73 : //!
74 : //! \note Don't reorder any fields here, the shifts and masks were defined carefully to make encoding of X86
75 : //! instructions fast, especially to construct REX, VEX, and EVEX prefixes in the most efficient way. Changing
76 : //! values defined by these enums many cause AsmJit to emit invalid binary representations of instructions passed to
77 : //! `x86::Assembler::_emit`.
78 : enum Bits : uint32_t {
79 : // MM & VEX & EVEX & XOP
80 : // ---------------------
81 : //
82 : // Two meanings:
83 : // * Part of a legacy opcode (prefixes emitted before the main opcode byte).
84 : // * `MMMMM` field in VEX|EVEX|XOP instruction.
85 : //
86 : // AVX reserves 5 bits for `MMMMM` field, however AVX instructions only use 2 bits and XOP 3 bits. AVX-512 shrinks
87 : // `MMMMM` field into `MMM` so it's safe to use [4:3] bits of `MMMMM` field for internal payload.
88 : //
89 : // AsmJit divides MMMMM field into this layout:
90 : //
91 : // [2:0] - Used to describe 0F, 0F38 and 0F3A legacy prefix bytes and 3 bits of MMMMM field for XOP/AVX/AVX512.
92 : // [3] - Required by XOP instructions, so we use this bit also to indicate that this is a XOP opcode.
93 : // [4] - Used to force EVEX prefix - this bit is not used by any X86 instruction yet, so AsmJit uses it to
94 : // describe EVEX only instructions or sets its bit when user uses InstOptions::kX86_Evex to force EVEX.
95 : kMM_Shift = 8,
96 : kMM_Mask = 0x1Fu << kMM_Shift,
97 : kMM_00 = 0x00u << kMM_Shift,
98 : kMM_0F = 0x01u << kMM_Shift,
99 : kMM_0F38 = 0x02u << kMM_Shift,
100 : kMM_0F3A = 0x03u << kMM_Shift, // Described also as XOP.M3 in AMD manuals.
101 : kMM_0F01 = 0x04u << kMM_Shift, // AsmJit way to describe 0F01 (never VEX/EVEX).
102 :
103 : kMM_MAP5 = 0x05u << kMM_Shift, // EVEX.MAP5.
104 : kMM_MAP6 = 0x06u << kMM_Shift, // EVEX.MAP6.
105 :
106 : // `XOP` field is only used to force XOP prefix instead of VEX3 prefix. We know XOP encodings always use 0b1000
107 : // bit of MM field and that no VEX and EVEX instruction use such bit yet, so we can use this bit to force XOP
108 : // prefix to be emitted instead of VEX3 prefix. See `x86VEXPrefix` defined in `x86assembler.cpp`.
109 : kMM_XOP08 = 0x08u << kMM_Shift, // XOP.M8.
110 : kMM_XOP09 = 0x09u << kMM_Shift, // XOP.M9.
111 : kMM_XOP0A = 0x0Au << kMM_Shift, // XOP.MA.
112 :
113 : kMM_IsXOP_Shift= kMM_Shift + 3,
114 : kMM_IsXOP = kMM_XOP08,
115 :
116 : // NOTE: Force VEX3 allows to force to emit VEX3 instead of VEX2 in some cases (similar to forcing REX prefix).
117 : // Force EVEX will force emitting EVEX prefix instead of VEX2|VEX3. EVEX-only instructions will have ForceEvex
118 : // always set, however. instructions that can be encoded by either VEX or EVEX prefix should not have ForceEvex
119 : // set.
120 : kMM_ForceEvex = 0x10u << kMM_Shift, // Force 4-BYTE EVEX prefix.
121 :
122 : // FPU_2B - Second-Byte of the Opcode used by FPU
123 : // ----------------------------------------------
124 : //
125 : // Second byte opcode. This BYTE is ONLY used by FPU instructions and collides with 3 bits from `MM` and 5 bits
126 : // from 'CDSHL' and 'CDTT'. It's fine as FPU and AVX512 flags are never used at the same time.
127 : kFPU_2B_Shift = 10,
128 : kFPU_2B_Mask = 0xFF << kFPU_2B_Shift,
129 :
130 : // CDSHL & CDTT
131 : // ------------
132 : //
133 : // Compressed displacement bits.
134 : //
135 : // Each opcode defines the base size (N) shift:
136 : // [0]: BYTE (1 byte).
137 : // [1]: WORD (2 bytes).
138 : // [2]: DWORD (4 bytes - float/int32).
139 : // [3]: QWORD (8 bytes - double/int64).
140 : // [4]: OWORD (16 bytes - used by FV|FVM|M128).
141 : //
142 : // Which is then scaled by the instruction's TT (TupleType) into possible:
143 : // [5]: YWORD (32 bytes)
144 : // [6]: ZWORD (64 bytes)
145 : //
146 : // These bits are then adjusted before calling EmitModSib or EmitModVSib.
147 : kCDSHL_Shift = 13,
148 : kCDSHL_Mask = 0x7u << kCDSHL_Shift,
149 :
150 : kCDSHL__ = 0x0u << kCDSHL_Shift, // Base element size not used.
151 : kCDSHL_0 = 0x0u << kCDSHL_Shift, // N << 0.
152 : kCDSHL_1 = 0x1u << kCDSHL_Shift, // N << 1.
153 : kCDSHL_2 = 0x2u << kCDSHL_Shift, // N << 2.
154 : kCDSHL_3 = 0x3u << kCDSHL_Shift, // N << 3.
155 : kCDSHL_4 = 0x4u << kCDSHL_Shift, // N << 4.
156 : kCDSHL_5 = 0x5u << kCDSHL_Shift, // N << 5.
157 :
158 : // Compressed displacement tuple-type (specific to AsmJit).
159 : //
160 : // Since we store the base offset independently of CDTT we can simplify the number of 'TUPLE_TYPE' groups
161 : // significantly and just handle special cases.
162 : kCDTT_Shift = 16,
163 : kCDTT_Mask = 0x3u << kCDTT_Shift,
164 : kCDTT_None = 0x0u << kCDTT_Shift, // Does nothing.
165 : kCDTT_ByLL = 0x1u << kCDTT_Shift, // Scales by LL (1x 2x 4x).
166 : kCDTT_T1W = 0x2u << kCDTT_Shift, // Used to add 'W' to the shift.
167 : kCDTT_DUP = 0x3u << kCDTT_Shift, // Special 'VMOVDDUP' case.
168 :
169 : // Aliases that match names used in instruction manuals.
170 : kCDTT__ = kCDTT_None,
171 : kCDTT_FV = kCDTT_ByLL,
172 : kCDTT_HV = kCDTT_ByLL,
173 : kCDTT_QV = kCDTT_ByLL,
174 : kCDTT_FVM = kCDTT_ByLL,
175 : kCDTT_T1S = kCDTT_None,
176 : kCDTT_T1F = kCDTT_None,
177 : kCDTT_T1_4X = kCDTT_None,
178 : kCDTT_T4X = kCDTT_None, // Alias to have only 3 letters.
179 : kCDTT_T2 = kCDTT_None,
180 : kCDTT_T4 = kCDTT_None,
181 : kCDTT_T8 = kCDTT_None,
182 : kCDTT_HVM = kCDTT_ByLL,
183 : kCDTT_QVM = kCDTT_ByLL,
184 : kCDTT_OVM = kCDTT_ByLL,
185 : kCDTT_128 = kCDTT_None,
186 :
187 : // `O` Field in ModR/M (??:xxx:???)
188 : // --------------------------------
189 :
190 : kModO_Shift = 18,
191 : kModO_Mask = 0x7u << kModO_Shift,
192 :
193 : kModO__ = 0x0u,
194 : kModO_0 = 0x0u << kModO_Shift,
195 : kModO_1 = 0x1u << kModO_Shift,
196 : kModO_2 = 0x2u << kModO_Shift,
197 : kModO_3 = 0x3u << kModO_Shift,
198 : kModO_4 = 0x4u << kModO_Shift,
199 : kModO_5 = 0x5u << kModO_Shift,
200 : kModO_6 = 0x6u << kModO_Shift,
201 : kModO_7 = 0x7u << kModO_Shift,
202 :
203 : // `RM` Field in ModR/M (??:???:xxx)
204 : // ---------------------------------
205 : //
206 : // Second data field used by ModR/M byte. This is only used by few instructions that use OPCODE+MOD/RM where both
207 : // values in Mod/RM are part of the opcode.
208 :
209 : kModRM_Shift = 13,
210 : kModRM_Mask = 0x7u << kModRM_Shift,
211 :
212 : kModRM__ = 0x0u,
213 : kModRM_0 = 0x0u << kModRM_Shift,
214 : kModRM_1 = 0x1u << kModRM_Shift,
215 : kModRM_2 = 0x2u << kModRM_Shift,
216 : kModRM_3 = 0x3u << kModRM_Shift,
217 : kModRM_4 = 0x4u << kModRM_Shift,
218 : kModRM_5 = 0x5u << kModRM_Shift,
219 : kModRM_6 = 0x6u << kModRM_Shift,
220 : kModRM_7 = 0x7u << kModRM_Shift,
221 :
222 : // `PP` Field
223 : // ----------
224 : //
225 : // These fields are stored deliberately right after each other as it makes it easier to construct VEX prefix from
226 : // the opcode value stored in the instruction database.
227 : //
228 : // Two meanings:
229 : // * "PP" field in AVX/XOP/AVX-512 instruction.
230 : // * Mandatory Prefix in legacy encoding.
231 : //
232 : // AVX reserves 2 bits for `PP` field, but AsmJit extends the storage by 1 more bit that is used to emit 9B prefix
233 : // for some X87-FPU instructions.
234 :
235 : kPP_Shift = 21,
236 : kPP_VEXMask = 0x03u << kPP_Shift, // PP field mask used by VEX/EVEX.
237 : kPP_FPUMask = 0x07u << kPP_Shift, // Mask used by EMIT_PP, also includes '0x9B'.
238 : kPP_00 = 0x00u << kPP_Shift,
239 : kPP_66 = 0x01u << kPP_Shift,
240 : kPP_F3 = 0x02u << kPP_Shift,
241 : kPP_F2 = 0x03u << kPP_Shift,
242 :
243 : kPP_9B = 0x07u << kPP_Shift, // AsmJit specific to emit FPU's '9B' byte.
244 :
245 : // REX|VEX|EVEX B|X|R|W Bits
246 : // -------------------------
247 : //
248 : // NOTE: REX.[B|X|R] are never stored within the opcode itself, they are reserved by AsmJit are are added
249 : // dynamically to the opcode to represent [REX|VEX|EVEX].[B|X|R] bits. REX.W can be stored in DB as it's sometimes
250 : // part of the opcode itself.
251 :
252 : // These must be binary compatible with instruction options.
253 : kREX_Shift = 24,
254 : kREX_Mask = 0x0Fu << kREX_Shift,
255 : kB = 0x01u << kREX_Shift, // Never stored in DB, used by encoder.
256 : kX = 0x02u << kREX_Shift, // Never stored in DB, used by encoder.
257 : kR = 0x04u << kREX_Shift, // Never stored in DB, used by encoder.
258 : kW = 0x08u << kREX_Shift,
259 : kW_Shift = kREX_Shift + 3,
260 :
261 : kW__ = 0u << kW_Shift, // REX.W/VEX.W is unspecified.
262 : kW_x = 0u << kW_Shift, // REX.W/VEX.W is based on instruction operands.
263 : kW_I = 0u << kW_Shift, // REX.W/VEX.W is ignored (WIG).
264 : kW_0 = 0u << kW_Shift, // REX.W/VEX.W is 0 (W0).
265 : kW_1 = 1u << kW_Shift, // REX.W/VEX.W is 1 (W1).
266 :
267 : // EVEX.W Field
268 : // ------------
269 : //
270 : // `W` field used by EVEX instruction encoding.
271 :
272 : kEvex_W_Shift = 28,
273 : kEvex_W_Mask = 1u << kEvex_W_Shift,
274 :
275 : kEvex_W__ = 0u << kEvex_W_Shift, // EVEX.W is unspecified (not EVEX instruction).
276 : kEvex_W_x = 0u << kEvex_W_Shift, // EVEX.W is based on instruction operands.
277 : kEvex_W_I = 0u << kEvex_W_Shift, // EVEX.W is ignored (WIG).
278 : kEvex_W_0 = 0u << kEvex_W_Shift, // EVEX.W is 0 (W0).
279 : kEvex_W_1 = 1u << kEvex_W_Shift, // EVEX.W is 1 (W1).
280 :
281 : // `L` or `LL` field in AVX/XOP/AVX-512
282 : // ------------------------------------
283 : //
284 : // VEX/XOP prefix can only use the first bit `L.128` or `L.256`. EVEX prefix prefix makes it possible to use also
285 : // `L.512`. If the instruction set manual describes an instruction by `LIG` it means that the `L` field is ignored
286 : // and AsmJit defaults to `0` in such case.
287 : kLL_Shift = 29,
288 : kLL_Mask = 0x3u << kLL_Shift,
289 :
290 : kLL__ = 0x0u << kLL_Shift, // LL is unspecified.
291 : kLL_x = 0x0u << kLL_Shift, // LL is based on instruction operands.
292 : kLL_I = 0x0u << kLL_Shift, // LL is ignored (LIG).
293 : kLL_0 = 0x0u << kLL_Shift, // LL is 0 (L.128).
294 : kLL_1 = 0x1u << kLL_Shift, // LL is 1 (L.256).
295 : kLL_2 = 0x2u << kLL_Shift, // LL is 2 (L.512).
296 :
297 : // Opcode Combinations
298 : // -------------------
299 :
300 : k0 = 0, // '__' (no prefix, used internally).
301 : k000000 = kPP_00 | kMM_00, // '__' (no prefix, to be the same width as others).
302 : k000F00 = kPP_00 | kMM_0F, // '0F'
303 : k000F01 = kPP_00 | kMM_0F01, // '0F01'
304 : k000F0F = kPP_00 | kMM_0F, // '0F0F' - 3DNOW, equal to 0x0F, must have special encoding to take effect.
305 : k000F38 = kPP_00 | kMM_0F38, // 'NP.0F38'
306 : k000F3A = kPP_00 | kMM_0F3A, // 'NP.0F3A'
307 : k00MAP5 = kPP_00 | kMM_MAP5, // 'NP.MAP5'
308 : k00MAP6 = kPP_00 | kMM_MAP6, // 'NP.MAP5'
309 : k660000 = kPP_66 | kMM_00, // '66'
310 : k660F00 = kPP_66 | kMM_0F, // '66.0F'
311 : k660F01 = kPP_66 | kMM_0F01, // '66.0F01'
312 : k660F38 = kPP_66 | kMM_0F38, // '66.0F38'
313 : k660F3A = kPP_66 | kMM_0F3A, // '66.0F3A'
314 : k66MAP5 = kPP_66 | kMM_MAP5, // '66.MAP5'
315 : k66MAP6 = kPP_66 | kMM_MAP6, // '66.MAP5'
316 : kF20000 = kPP_F2 | kMM_00, // 'F2'
317 : kF20F00 = kPP_F2 | kMM_0F, // 'F2.0F'
318 : kF20F01 = kPP_F2 | kMM_0F01, // 'F2.0F01'
319 : kF20F38 = kPP_F2 | kMM_0F38, // 'F2.0F38'
320 : kF20F3A = kPP_F2 | kMM_0F3A, // 'F2.0F3A'
321 : kF2MAP5 = kPP_F2 | kMM_MAP5, // 'F2.MAP5'
322 : kF2MAP6 = kPP_F2 | kMM_MAP6, // 'F2.MAP5'
323 : kF30000 = kPP_F3 | kMM_00, // 'F3'
324 : kF30F00 = kPP_F3 | kMM_0F, // 'F3.0F'
325 : kF30F01 = kPP_F3 | kMM_0F01, // 'F3.0F01'
326 : kF30F38 = kPP_F3 | kMM_0F38, // 'F3.0F38'
327 : kF30F3A = kPP_F3 | kMM_0F3A, // 'F3.0F3A'
328 : kF3MAP5 = kPP_F3 | kMM_MAP5, // 'F3.MAP5'
329 : kF3MAP6 = kPP_F3 | kMM_MAP6, // 'F3.MAP5'
330 : kFPU_00 = kPP_00 | kMM_00, // '__' (FPU)
331 : kFPU_9B = kPP_9B | kMM_00, // '9B' (FPU)
332 : kXOP_M8 = kPP_00 | kMM_XOP08, // 'M8' (XOP)
333 : kXOP_M9 = kPP_00 | kMM_XOP09, // 'M9' (XOP)
334 : kXOP_MA = kPP_00 | kMM_XOP0A // 'MA' (XOP)
335 : };
336 :
337 : // Opcode Builder
338 : // --------------
339 :
340 : inline uint32_t get() const noexcept { return v; }
341 :
342 : inline bool hasW() const noexcept { return (v & kW) != 0; }
343 : inline bool has66h() const noexcept { return (v & kPP_66) != 0; }
344 :
345 : inline Opcode& add(uint32_t x) noexcept { return operator+=(x); }
346 :
347 : inline Opcode& add66h() noexcept { return operator|=(kPP_66); }
348 : template<typename T>
349 0 : inline Opcode& add66hIf(T exp) noexcept { return operator|=(uint32_t(exp) << kPP_Shift); }
350 : template<typename T>
351 0 : inline Opcode& add66hBySize(T size) noexcept { return add66hIf(size == 2); }
352 :
353 : inline Opcode& addW() noexcept { return operator|=(kW); }
354 : template<typename T>
355 9980 : inline Opcode& addWIf(T exp) noexcept { return operator|=(uint32_t(exp) << kW_Shift); }
356 : template<typename T>
357 9980 : inline Opcode& addWBySize(T size) noexcept { return addWIf(size == 8); }
358 :
359 : template<typename T>
360 : inline Opcode& addPrefixBySize(T size) noexcept {
361 : static const uint32_t mask[16] = {
362 : 0, // #0
363 : 0, // #1 -> nothing (already handled or not possible)
364 : kPP_66, // #2 -> 66H
365 : 0, // #3
366 : 0, // #4 -> nothing
367 : 0, // #5
368 : 0, // #6
369 : 0, // #7
370 : kW // #8 -> REX.W
371 : };
372 88236 : return operator|=(mask[size & 0xF]);
373 : }
374 :
375 : template<typename T>
376 : inline Opcode& addArithBySize(T size) noexcept {
377 : static const uint32_t mask[16] = {
378 : 0, // #0
379 : 0, // #1 -> nothing
380 : 1 | kPP_66, // #2 -> NOT_BYTE_OP(1) and 66H
381 : 0, // #3
382 : 1, // #4 -> NOT_BYTE_OP(1)
383 : 0, // #5
384 : 0, // #6
385 : 0, // #7
386 : 1 | kW // #8 -> NOT_BYTE_OP(1) and REX.W
387 : };
388 20 : return operator|=(mask[size & 0xF]);
389 : }
390 :
391 0 : inline Opcode& forceEvex() noexcept { return operator|=(kMM_ForceEvex); }
392 : template<typename T>
393 1970 : inline Opcode& forceEvexIf(T exp) noexcept { return operator|=(uint32_t(exp) << Support::ConstCTZ<uint32_t(kMM_ForceEvex)>::value); }
394 :
395 : //! Extract `O` field (R) from the opcode (specified as /0..7 in instruction manuals).
396 : inline uint32_t extractModO() const noexcept {
397 392009 : return (v >> kModO_Shift) & 0x07;
398 : }
399 :
400 : //! Extract `RM` field (RM) from the opcode (usually specified as another opcode value).
401 : inline uint32_t extractModRM() const noexcept {
402 0 : return (v >> kModRM_Shift) & 0x07;
403 : }
404 :
405 : //! Extract `REX` prefix from opcode combined with `options`.
406 : inline uint32_t extractRex(InstOptions options) const noexcept {
407 : // kREX was designed in a way that when shifted there will be no bytes set except REX.[B|X|R|W].
408 : // The returned value forms a real REX prefix byte. This case should be unit-tested as well.
409 135367 : return (v | uint32_t(options)) >> kREX_Shift;
410 : }
411 :
412 : inline uint32_t extractLLMMMMM(InstOptions options) const noexcept {
413 256642 : uint32_t llMmmmm = uint32_t(v & (kLL_Mask | kMM_Mask));
414 : uint32_t vexEvex = uint32_t(options & InstOptions::kX86_Evex);
415 256642 : return (llMmmmm | vexEvex) >> kMM_Shift;
416 : }
417 :
418 : inline Opcode& operator=(uint32_t x) noexcept { v = x; return *this; }
419 125728 : inline Opcode& operator+=(uint32_t x) noexcept { v += x; return *this; }
420 0 : inline Opcode& operator-=(uint32_t x) noexcept { v -= x; return *this; }
421 142085 : inline Opcode& operator&=(uint32_t x) noexcept { v &= x; return *this; }
422 490225 : inline Opcode& operator|=(uint32_t x) noexcept { v |= x; return *this; }
423 : inline Opcode& operator^=(uint32_t x) noexcept { v ^= x; return *this; }
424 :
425 0 : inline uint32_t operator&(uint32_t x) const noexcept { return v & x; }
426 : inline uint32_t operator|(uint32_t x) const noexcept { return v | x; }
427 : inline uint32_t operator^(uint32_t x) const noexcept { return v ^ x; }
428 2610 : inline uint32_t operator<<(uint32_t x) const noexcept { return v << x; }
429 256642 : inline uint32_t operator>>(uint32_t x) const noexcept { return v >> x; }
430 : };
431 :
432 : //! \}
433 : //! \endcond
434 :
435 : ASMJIT_END_SUB_NAMESPACE
436 :
437 : #endif // ASMJIT_X86_X86OPCODE_P_H_INCLUDED
438 :
439 : #endif // __PLUMED_HAS_ASMJIT
|