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_X86INSTDB_H_INCLUDED
8 : #define ASMJIT_X86_X86INSTDB_H_INCLUDED
9 :
10 : #include "x86globals.h"
11 :
12 : ASMJIT_BEGIN_SUB_NAMESPACE(x86)
13 :
14 : //! \addtogroup asmjit_x86
15 : //! \{
16 :
17 : //! Instruction database (X86).
18 : namespace InstDB {
19 :
20 : //! Describes which operation mode is supported by an instruction.
21 : enum class Mode : uint8_t {
22 : //! Invalid mode.
23 : kNone = 0x00u,
24 : //! X86 mode supported.
25 : kX86 = 0x01u,
26 : //! X64 mode supported.
27 : kX64 = 0x02u,
28 : //! Both X86 and X64 modes supported.
29 : kAny = 0x03u
30 : };
31 : ASMJIT_DEFINE_ENUM_FLAGS(Mode)
32 :
33 : //! Converts architecture to operation mode, see \ref Mode.
34 0 : static constexpr Mode modeFromArch(Arch arch) noexcept {
35 0 : return arch == Arch::kX86 ? Mode::kX86 :
36 0 : arch == Arch::kX64 ? Mode::kX64 : Mode::kNone;
37 : }
38 :
39 : //! Operand signature flags used by \ref OpSignature.
40 : enum class OpFlags : uint64_t {
41 : //! No operand flags.
42 : kNone = 0u,
43 :
44 : kRegGpbLo = 0x0000000000000001u, //!< Operand can be low 8-bit GPB register.
45 : kRegGpbHi = 0x0000000000000002u, //!< Operand can be high 8-bit GPB register.
46 : kRegGpw = 0x0000000000000004u, //!< Operand can be 16-bit GPW register.
47 : kRegGpd = 0x0000000000000008u, //!< Operand can be 32-bit GPD register.
48 : kRegGpq = 0x0000000000000010u, //!< Operand can be 64-bit GPQ register.
49 : kRegXmm = 0x0000000000000020u, //!< Operand can be 128-bit XMM register.
50 : kRegYmm = 0x0000000000000040u, //!< Operand can be 256-bit YMM register.
51 : kRegZmm = 0x0000000000000080u, //!< Operand can be 512-bit ZMM register.
52 : kRegMm = 0x0000000000000100u, //!< Operand can be 64-bit MM register.
53 : kRegKReg = 0x0000000000000200u, //!< Operand can be 64-bit K register.
54 : kRegSReg = 0x0000000000000400u, //!< Operand can be SReg (segment register).
55 : kRegCReg = 0x0000000000000800u, //!< Operand can be CReg (control register).
56 : kRegDReg = 0x0000000000001000u, //!< Operand can be DReg (debug register).
57 : kRegSt = 0x0000000000002000u, //!< Operand can be 80-bit ST register (X87).
58 : kRegBnd = 0x0000000000004000u, //!< Operand can be 128-bit BND register.
59 : kRegTmm = 0x0000000000008000u, //!< Operand can be 0..8192-bit TMM register.
60 : kRegMask = 0x000000000000FFFFu, //!< Mask of all possible register types.
61 :
62 : kMemUnspecified = 0x0000000000040000u, //!< Operand can be a scalar memory pointer without size.
63 : kMem8 = 0x0000000000080000u, //!< Operand can be an 8-bit memory pointer.
64 : kMem16 = 0x0000000000100000u, //!< Operand can be a 16-bit memory pointer.
65 : kMem32 = 0x0000000000200000u, //!< Operand can be a 32-bit memory pointer.
66 : kMem48 = 0x0000000000400000u, //!< Operand can be a 48-bit memory pointer (FAR pointers only).
67 : kMem64 = 0x0000000000800000u, //!< Operand can be a 64-bit memory pointer.
68 : kMem80 = 0x0000000001000000u, //!< Operand can be an 80-bit memory pointer.
69 : kMem128 = 0x0000000002000000u, //!< Operand can be a 128-bit memory pointer.
70 : kMem256 = 0x0000000004000000u, //!< Operand can be a 256-bit memory pointer.
71 : kMem512 = 0x0000000008000000u, //!< Operand can be a 512-bit memory pointer.
72 : kMem1024 = 0x0000000010000000u, //!< Operand can be a 1024-bit memory pointer.
73 : kMemMask = 0x000000001FFC0000u, //!< Mask of all possible scalar memory types.
74 :
75 : kVm32x = 0x0000000040000000u, //!< Operand can be a vm32x (vector) pointer.
76 : kVm32y = 0x0000000080000000u, //!< Operand can be a vm32y (vector) pointer.
77 : kVm32z = 0x0000000100000000u, //!< Operand can be a vm32z (vector) pointer.
78 : kVm64x = 0x0000000200000000u, //!< Operand can be a vm64x (vector) pointer.
79 : kVm64y = 0x0000000400000000u, //!< Operand can be a vm64y (vector) pointer.
80 : kVm64z = 0x0000000800000000u, //!< Operand can be a vm64z (vector) pointer.
81 : kVmMask = 0x0000000FC0000000u, //!< Mask of all possible vector memory types.
82 :
83 : kImmI4 = 0x0000001000000000u, //!< Operand can be signed 4-bit immediate.
84 : kImmU4 = 0x0000002000000000u, //!< Operand can be unsigned 4-bit immediate.
85 : kImmI8 = 0x0000004000000000u, //!< Operand can be signed 8-bit immediate.
86 : kImmU8 = 0x0000008000000000u, //!< Operand can be unsigned 8-bit immediate.
87 : kImmI16 = 0x0000010000000000u, //!< Operand can be signed 16-bit immediate.
88 : kImmU16 = 0x0000020000000000u, //!< Operand can be unsigned 16-bit immediate.
89 : kImmI32 = 0x0000040000000000u, //!< Operand can be signed 32-bit immediate.
90 : kImmU32 = 0x0000080000000000u, //!< Operand can be unsigned 32-bit immediate.
91 : kImmI64 = 0x0000100000000000u, //!< Operand can be signed 64-bit immediate.
92 : kImmU64 = 0x0000200000000000u, //!< Operand can be unsigned 64-bit immediate.
93 : kImmMask = 0x00003FF000000000u, //!< Mask of all immediate types.
94 :
95 : kRel8 = 0x0000400000000000u, //!< Operand can be relative 8-bit displacement.
96 : kRel32 = 0x0000800000000000u, //!< Operand can be relative 32-bit displacement.
97 : kRelMask = 0x0000C00000000000u, //!< Mask of all relative displacement types.
98 :
99 : kFlagMemBase = 0x0001000000000000u, //!< Flag: Only memory base is allowed (no index, no offset).
100 : kFlagMemDs = 0x0002000000000000u, //!< Flag: Implicit memory operand's DS segment.
101 : kFlagMemEs = 0x0004000000000000u, //!< Flag: Implicit memory operand's ES segment.
102 :
103 : kFlagMib = 0x0008000000000000u, //!< Flag: Operand is MIB (base+index) pointer.
104 : kFlagTMem = 0x0010000000000000u, //!< Flag: Operand is TMEM (sib_mem), AMX memory pointer.
105 :
106 : kFlagImplicit = 0x0080000000000000u, //!< Flag: Operand is implicit.
107 : kFlagMask = 0x009F000000000000u, //!< Mask of all flags.
108 :
109 : //! Contains mask of all registers, memory operands, immediate operands, and displacement operands.
110 : kOpMask = kRegMask | kMemMask | kVmMask | kImmMask | kRelMask
111 : };
112 0 : ASMJIT_DEFINE_ENUM_FLAGS(OpFlags)
113 :
114 : //! Operand signature.
115 : //!
116 : //! Contains all possible operand combinations, memory size information, and a fixed register id (or `BaseReg::kIdBad`
117 : //! if fixed id isn't required).
118 : struct OpSignature {
119 : //! \name Members
120 : //! \{
121 :
122 : uint64_t _flags : 56;
123 : uint64_t _regMask : 8;
124 :
125 : //! \}
126 :
127 : //! \name Accessors
128 : //! \{
129 :
130 : //! Returns operand signature flags.
131 0 : inline OpFlags flags() const noexcept { return (OpFlags)_flags; }
132 :
133 : //! Tests whether the given `flag` is set.
134 0 : inline bool hasFlag(OpFlags flag) const noexcept { return (_flags & uint64_t(flag)) != 0; }
135 :
136 : //! Tests whether this signature contains at least one register operand of any type.
137 : inline bool hasReg() const noexcept { return hasFlag(OpFlags::kRegMask); }
138 : //! Tests whether this signature contains at least one scalar memory operand of any type.
139 : inline bool hasMem() const noexcept { return hasFlag(OpFlags::kMemMask); }
140 : //! Tests whether this signature contains at least one vector memory operand of any type.
141 : inline bool hasVm() const noexcept { return hasFlag(OpFlags::kVmMask); }
142 : //! Tests whether this signature contains at least one immediate operand of any type.
143 : inline bool hasImm() const noexcept { return hasFlag(OpFlags::kImmMask); }
144 : //! Tests whether this signature contains at least one relative displacement operand of any type.
145 : inline bool hasRel() const noexcept { return hasFlag(OpFlags::kRelMask); }
146 :
147 : //! Tests whether the operand is implicit.
148 : inline bool isImplicit() const noexcept { return hasFlag(OpFlags::kFlagImplicit); }
149 :
150 : //! Returns a physical register mask.
151 0 : inline RegMask regMask() const noexcept { return _regMask; }
152 :
153 : //! \}
154 : };
155 :
156 : ASMJIT_VARAPI const OpSignature _opSignatureTable[];
157 :
158 : //! Instruction signature.
159 : //!
160 : //! Contains a sequence of operands' combinations and other metadata that defines a single instruction. This data is
161 : //! used by instruction validator.
162 : struct InstSignature {
163 : //! \name Members
164 : //! \{
165 :
166 : //! Count of operands in `opIndex` (0..6).
167 : uint8_t _opCount : 3;
168 : //! Architecture modes supported (X86 / X64).
169 : uint8_t _mode : 2;
170 : //! Number of implicit operands.
171 : uint8_t _implicitOpCount : 3;
172 : //! Reserved for future use.
173 : uint8_t _reserved;
174 : //! Indexes to `OpSignature` table.
175 : uint8_t _opSignatureIndexes[Globals::kMaxOpCount];
176 :
177 : //! \}
178 :
179 : //! \name Accessors
180 : //! \{
181 :
182 : //! Returns instruction operation mode.
183 : inline Mode mode() const noexcept { return (Mode)_mode; }
184 : //! Tests whether the instruction supports the given operating mode.
185 0 : inline bool supportsMode(Mode mode) const noexcept { return (uint8_t(_mode) & uint8_t(mode)) != 0; }
186 :
187 : //! Returns the number of operands of this signature.
188 0 : inline uint32_t opCount() const noexcept { return _opCount; }
189 : //! Returns the number of implicit operands this signature has.
190 0 : inline uint32_t implicitOpCount() const noexcept { return _implicitOpCount; }
191 : //! Tests whether this instruction signature has at least one implicit operand.
192 : inline bool hasImplicitOperands() const noexcept { return _implicitOpCount != 0; }
193 :
194 : //! Returns indexes to \ref _opSignatureTable for each operand of the instruction.
195 : //!
196 : //! \note The returned array always provides indexes for all operands (see \ref Globals::kMaxOpCount) even if the
197 : //! instruction provides less operands. Undefined operands have always index of zero.
198 : inline const uint8_t* opSignatureIndexes() const noexcept { return _opSignatureIndexes; }
199 :
200 : //! Returns index to \ref _opSignatureTable, corresponding to the requested operand `index` of the instruction.
201 : inline uint8_t opSignatureIndex(size_t index) const noexcept {
202 : ASMJIT_ASSERT(index < Globals::kMaxOpCount);
203 0 : return _opSignatureIndexes[index];
204 : }
205 :
206 : //! Returns \ref OpSignature corresponding to the requested operand `index` of the instruction.
207 : inline const OpSignature& opSignature(size_t index) const noexcept {
208 : ASMJIT_ASSERT(index < Globals::kMaxOpCount);
209 0 : return _opSignatureTable[_opSignatureIndexes[index]];
210 : }
211 :
212 : //! \}
213 : };
214 :
215 : ASMJIT_VARAPI const InstSignature _instSignatureTable[];
216 :
217 : //! Instruction flags.
218 : //!
219 : //! Details about instruction encoding, operation, features, and some limitations.
220 : enum class InstFlags : uint32_t {
221 : //! No flags.
222 : kNone = 0x00000000u,
223 :
224 : // Instruction Family
225 : // ------------------
226 : //
227 : // Instruction family information.
228 :
229 : //! Instruction that accesses FPU registers.
230 : kFpu = 0x00000100u,
231 : //! Instruction that accesses MMX registers (including 3DNOW and GEODE) and EMMS.
232 : kMmx = 0x00000200u,
233 : //! Instruction that accesses XMM registers (SSE, AVX, AVX512).
234 : kVec = 0x00000400u,
235 :
236 : // FPU Flags
237 : // ---------
238 : //
239 : // Used to tell the encoder which memory operand sizes are encodable.
240 :
241 : //! FPU instruction can address `word_ptr` (shared with M80).
242 : kFpuM16 = 0x00000800u,
243 : //! FPU instruction can address `dword_ptr`.
244 : kFpuM32 = 0x00001000u,
245 : //! FPU instruction can address `qword_ptr`.
246 : kFpuM64 = 0x00002000u,
247 : //! FPU instruction can address `tword_ptr` (shared with M16).
248 : kFpuM80 = 0x00000800u,
249 :
250 : // Prefixes and Encoding Flags
251 : // ---------------------------
252 : //
253 : // These describe optional X86 prefixes that can be used to change the instruction's operation.
254 :
255 : //! Instruction can be prefixed with using the REP(REPE) or REPNE prefix.
256 : kRep = 0x00004000u,
257 : //! Rep prefix is accepted, but it has no effect other than being emitted with the instruction (as an extra byte).
258 : kRepIgnored = 0x00008000u,
259 : //! Instruction can be prefixed with using the LOCK prefix.
260 : kLock = 0x00010000u,
261 : //! Instruction can be prefixed with using the XACQUIRE prefix.
262 : kXAcquire = 0x00020000u,
263 : //! Instruction can be prefixed with using the XRELEASE prefix.
264 : kXRelease = 0x00040000u,
265 : //! Instruction uses MIB (BNDLDX|BNDSTX) to encode two registers.
266 : kMib = 0x00080000u,
267 : //! Instruction uses VSIB instead of legacy SIB.
268 : kVsib = 0x00100000u,
269 : //! Instruction uses TSIB (or SIB_MEM) encoding (MODRM followed by SIB).
270 : kTsib = 0x00200000u,
271 :
272 : // If both `kPrefixVex` and `kPrefixEvex` flags are specified it means that the instructions can be encoded
273 : // by either VEX or EVEX prefix. In that case AsmJit checks global options and also instruction options to decide
274 : // whether to emit VEX or EVEX prefix.
275 :
276 : //! Instruction can be encoded by VEX|XOP (AVX|AVX2|BMI|XOP|...).
277 : kVex = 0x00400000u,
278 : //! Instruction can be encoded by EVEX (AVX512).
279 : kEvex = 0x00800000u,
280 : //! EVEX encoding is preferred over VEX encoding (AVX515_VNNI vs AVX_VNNI).
281 : kPreferEvex = 0x01000000u,
282 : //! EVEX and VEX signatures are compatible.
283 : kEvexCompat = 0x02000000u,
284 : //! EVEX instruction requires K register in the first operand (compare instructions).
285 : kEvexKReg = 0x04000000u,
286 : //! EVEX instruction requires two operands and K register as a selector (gather instructions).
287 : kEvexTwoOp = 0x08000000u,
288 : //! VEX instruction that can be transformed to a compatible EVEX instruction.
289 : kEvexTransformable = 0x10000000u,
290 :
291 : // Other Flags
292 : // -----------
293 :
294 : //! Instruction uses consecutive registers.
295 : //!
296 : //! Used by V4FMADDPS, V4FMADDSS, V4FNMADDPS, V4FNMADDSS, VP4DPWSSD, VP4DPWSSDS, VP2INTERSECTD, and VP2INTERSECTQ
297 : //! instructions
298 : kConsecutiveRegs = 0x20000000u
299 : };
300 142085 : ASMJIT_DEFINE_ENUM_FLAGS(InstFlags)
301 :
302 : //! AVX-512 flags.
303 : enum class Avx512Flags : uint32_t {
304 : //! No AVX-512 flags.
305 : kNone = 0,
306 :
307 : //! Internally used in tables, has no meaning.
308 : k_ = 0x00000000u,
309 : //! Supports masking {k1..k7}.
310 : kK = 0x00000001u,
311 : //! Supports zeroing {z}, must be used together with `kAvx512k`.
312 : kZ = 0x00000002u,
313 : //! Supports 'embedded-rounding' {er} with implicit {sae},
314 : kER = 0x00000004u,
315 : //! Supports 'suppress-all-exceptions' {sae}.
316 : kSAE = 0x00000008u,
317 : //! Supports 16-bit broadcast 'b16'.
318 : kB16 = 0x00000010u,
319 : //! Supports 32-bit broadcast 'b32'.
320 : kB32 = 0x00000020u,
321 : //! Supports 64-bit broadcast 'b64'.
322 : kB64 = 0x00000040u,
323 : //! Operates on a vector of consecutive registers (AVX512_4FMAPS and AVX512_4VNNIW).
324 : kT4X = 0x00000080u,
325 :
326 : //! Implicit zeroing if {k} masking is used. Using {z} is not valid in this case as it's implicit.
327 : kImplicitZ = 0x00000100,
328 : };
329 : ASMJIT_DEFINE_ENUM_FLAGS(Avx512Flags)
330 :
331 : //! Instruction common information.
332 : //!
333 : //! Aggregated information shared across one or more instruction.
334 : struct CommonInfo {
335 : //! Instruction flags.
336 : uint32_t _flags;
337 : //! Reserved for future use.
338 : uint32_t _avx512Flags : 11;
339 : //! First `InstSignature` entry in the database.
340 : uint32_t _iSignatureIndex : 11;
341 : //! Number of relevant `ISignature` entries.
342 : uint32_t _iSignatureCount : 5;
343 : //! Instruction control flow category, see \ref InstControlFlow.
344 : uint32_t _controlFlow : 3;
345 : //! Specifies what happens if all source operands share the same register.
346 : uint32_t _sameRegHint : 2;
347 :
348 : //! \name Accessors
349 : //! \{
350 :
351 : //! Returns instruction flags.
352 142085 : inline InstFlags flags() const noexcept { return (InstFlags)_flags; }
353 : //! Tests whether the instruction has a `flag`.
354 703063 : inline bool hasFlag(InstFlags flag) const noexcept { return Support::test(_flags, flag); }
355 :
356 : //! Returns instruction AVX-512 flags.
357 : inline Avx512Flags avx512Flags() const noexcept { return (Avx512Flags)_avx512Flags; }
358 : //! Tests whether the instruction has an AVX-512 `flag`.
359 0 : inline bool hasAvx512Flag(Avx512Flags flag) const noexcept { return Support::test(_avx512Flags, flag); }
360 :
361 : //! Tests whether the instruction is FPU instruction.
362 : inline bool isFpu() const noexcept { return hasFlag(InstFlags::kFpu); }
363 : //! Tests whether the instruction is MMX/3DNOW instruction that accesses MMX registers (includes EMMS and FEMMS).
364 : inline bool isMmx() const noexcept { return hasFlag(InstFlags::kMmx); }
365 : //! Tests whether the instruction is SSE|AVX|AVX512 instruction that accesses XMM|YMM|ZMM registers.
366 : inline bool isVec() const noexcept { return hasFlag(InstFlags::kVec); }
367 : //! Tests whether the instruction is SSE+ (SSE4.2, AES, SHA included) instruction that accesses XMM registers.
368 : inline bool isSse() const noexcept { return (flags() & (InstFlags::kVec | InstFlags::kVex | InstFlags::kEvex)) == InstFlags::kVec; }
369 : //! Tests whether the instruction is AVX+ (FMA included) instruction that accesses XMM|YMM|ZMM registers.
370 : inline bool isAvx() const noexcept { return isVec() && isVexOrEvex(); }
371 :
372 : //! Tests whether the instruction can be prefixed with LOCK prefix.
373 : inline bool hasLockPrefix() const noexcept { return hasFlag(InstFlags::kLock); }
374 : //! Tests whether the instruction can be prefixed with REP (REPE|REPZ) prefix.
375 : inline bool hasRepPrefix() const noexcept { return hasFlag(InstFlags::kRep); }
376 : //! Tests whether the instruction can be prefixed with XACQUIRE prefix.
377 : inline bool hasXAcquirePrefix() const noexcept { return hasFlag(InstFlags::kXAcquire); }
378 : //! Tests whether the instruction can be prefixed with XRELEASE prefix.
379 : inline bool hasXReleasePrefix() const noexcept { return hasFlag(InstFlags::kXRelease); }
380 :
381 : //! Tests whether the rep prefix is supported by the instruction, but ignored (has no effect).
382 : inline bool isRepIgnored() const noexcept { return hasFlag(InstFlags::kRepIgnored); }
383 : //! Tests whether the instruction uses MIB.
384 : inline bool isMibOp() const noexcept { return hasFlag(InstFlags::kMib); }
385 : //! Tests whether the instruction uses VSIB.
386 : inline bool isVsibOp() const noexcept { return hasFlag(InstFlags::kVsib); }
387 : //! Tests whether the instruction uses TSIB (AMX, instruction requires MOD+SIB).
388 : inline bool isTsibOp() const noexcept { return hasFlag(InstFlags::kTsib); }
389 : //! Tests whether the instruction uses VEX (can be set together with EVEX if both are encodable).
390 : inline bool isVex() const noexcept { return hasFlag(InstFlags::kVex); }
391 : //! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable).
392 : inline bool isEvex() const noexcept { return hasFlag(InstFlags::kEvex); }
393 : //! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable).
394 : inline bool isVexOrEvex() const noexcept { return hasFlag(InstFlags::kVex | InstFlags::kEvex); }
395 :
396 : //! Tests whether the instruction should prefer EVEX prefix instead of VEX prefix.
397 : inline bool preferEvex() const noexcept { return hasFlag(InstFlags::kPreferEvex); }
398 :
399 : inline bool isEvexCompatible() const noexcept { return hasFlag(InstFlags::kEvexCompat); }
400 : inline bool isEvexKRegOnly() const noexcept { return hasFlag(InstFlags::kEvexKReg); }
401 : inline bool isEvexTwoOpOnly() const noexcept { return hasFlag(InstFlags::kEvexTwoOp); }
402 : inline bool isEvexTransformable() const noexcept { return hasFlag(InstFlags::kEvexTransformable); }
403 :
404 : //! Tests whether the instruction supports AVX512 masking {k}.
405 : inline bool hasAvx512K() const noexcept { return hasAvx512Flag(Avx512Flags::kK); }
406 : //! Tests whether the instruction supports AVX512 zeroing {k}{z}.
407 : inline bool hasAvx512Z() const noexcept { return hasAvx512Flag(Avx512Flags::kZ); }
408 : //! Tests whether the instruction supports AVX512 embedded-rounding {er}.
409 : inline bool hasAvx512ER() const noexcept { return hasAvx512Flag(Avx512Flags::kER); }
410 : //! Tests whether the instruction supports AVX512 suppress-all-exceptions {sae}.
411 : inline bool hasAvx512SAE() const noexcept { return hasAvx512Flag(Avx512Flags::kSAE); }
412 : //! Tests whether the instruction supports AVX512 broadcast (either 32-bit or 64-bit).
413 : inline bool hasAvx512B() const noexcept { return hasAvx512Flag(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64); }
414 : //! Tests whether the instruction supports AVX512 broadcast (16-bit).
415 : inline bool hasAvx512B16() const noexcept { return hasAvx512Flag(Avx512Flags::kB16); }
416 : //! Tests whether the instruction supports AVX512 broadcast (32-bit).
417 : inline bool hasAvx512B32() const noexcept { return hasAvx512Flag(Avx512Flags::kB32); }
418 : //! Tests whether the instruction supports AVX512 broadcast (64-bit).
419 : inline bool hasAvx512B64() const noexcept { return hasAvx512Flag(Avx512Flags::kB64); }
420 :
421 : // Returns the size of the broadcast - either 2, 4, or 8, or 0 if broadcast is not supported.
422 : inline uint32_t broadcastSize() const noexcept {
423 : constexpr uint32_t kShift = Support::ConstCTZ<uint32_t(Avx512Flags::kB16)>::value;
424 0 : return (uint32_t(_avx512Flags) & uint32_t(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64)) >> (kShift - 1);
425 : }
426 :
427 : inline uint32_t signatureIndex() const noexcept { return _iSignatureIndex; }
428 : inline uint32_t signatureCount() const noexcept { return _iSignatureCount; }
429 :
430 : inline const InstSignature* signatureData() const noexcept { return _instSignatureTable + _iSignatureIndex; }
431 : inline const InstSignature* signatureEnd() const noexcept { return _instSignatureTable + _iSignatureIndex + _iSignatureCount; }
432 :
433 : //! Returns a control flow category of the instruction.
434 304316 : inline InstControlFlow controlFlow() const noexcept { return (InstControlFlow)_controlFlow; }
435 :
436 : //! Returns a hint that can be used when both inputs are the same register.
437 28169 : inline InstSameRegHint sameRegHint() const noexcept { return (InstSameRegHint)_sameRegHint; }
438 :
439 : //! \}
440 : };
441 :
442 : ASMJIT_VARAPI const CommonInfo _commonInfoTable[];
443 :
444 : //! Instruction information.
445 : struct InstInfo {
446 : //! Index to \ref _nameData.
447 : uint32_t _nameDataIndex : 14;
448 : //! Index to \ref _commonInfoTable.
449 : uint32_t _commonInfoIndex : 10;
450 : //! Index to \ref _additionalInfoTable.
451 : uint32_t _additionalInfoIndex : 8;
452 :
453 : //! Instruction encoding (internal encoding identifier used by \ref Assembler).
454 : uint8_t _encoding;
455 : //! Main opcode value (0..255).
456 : uint8_t _mainOpcodeValue;
457 : //! Index to \ref _mainOpcodeTable` that is combined with \ref _mainOpcodeValue to form the final opcode.
458 : uint8_t _mainOpcodeIndex;
459 : //! Index to \ref _altOpcodeTable that contains a full alternative opcode.
460 : uint8_t _altOpcodeIndex;
461 :
462 : //! \name Accessors
463 : //! \{
464 :
465 : //! Returns common information, see \ref CommonInfo.
466 1056302 : inline const CommonInfo& commonInfo() const noexcept { return _commonInfoTable[_commonInfoIndex]; }
467 :
468 : //! Returns instruction flags, see \ref Flags.
469 : inline InstFlags flags() const noexcept { return commonInfo().flags(); }
470 : //! Tests whether the instruction has flag `flag`, see \ref Flags.
471 : inline bool hasFlag(InstFlags flag) const noexcept { return commonInfo().hasFlag(flag); }
472 :
473 : //! Returns instruction AVX-512 flags, see \ref Avx512Flags.
474 : inline Avx512Flags avx512Flags() const noexcept { return commonInfo().avx512Flags(); }
475 : //! Tests whether the instruction has an AVX-512 `flag`, see \ref Avx512Flags.
476 : inline bool hasAvx512Flag(Avx512Flags flag) const noexcept { return commonInfo().hasAvx512Flag(flag); }
477 :
478 : //! Tests whether the instruction is FPU instruction.
479 : inline bool isFpu() const noexcept { return commonInfo().isFpu(); }
480 : //! Tests whether the instruction is MMX/3DNOW instruction that accesses MMX registers (includes EMMS and FEMMS).
481 : inline bool isMmx() const noexcept { return commonInfo().isMmx(); }
482 : //! Tests whether the instruction is SSE|AVX|AVX512 instruction that accesses XMM|YMM|ZMM registers.
483 : inline bool isVec() const noexcept { return commonInfo().isVec(); }
484 : //! Tests whether the instruction is SSE+ (SSE4.2, AES, SHA included) instruction that accesses XMM registers.
485 : inline bool isSse() const noexcept { return commonInfo().isSse(); }
486 : //! Tests whether the instruction is AVX+ (FMA included) instruction that accesses XMM|YMM|ZMM registers.
487 : inline bool isAvx() const noexcept { return commonInfo().isAvx(); }
488 :
489 : //! Tests whether the instruction can be prefixed with LOCK prefix.
490 : inline bool hasLockPrefix() const noexcept { return commonInfo().hasLockPrefix(); }
491 : //! Tests whether the instruction can be prefixed with REP (REPE|REPZ) prefix.
492 : inline bool hasRepPrefix() const noexcept { return commonInfo().hasRepPrefix(); }
493 : //! Tests whether the instruction can be prefixed with XACQUIRE prefix.
494 : inline bool hasXAcquirePrefix() const noexcept { return commonInfo().hasXAcquirePrefix(); }
495 : //! Tests whether the instruction can be prefixed with XRELEASE prefix.
496 : inline bool hasXReleasePrefix() const noexcept { return commonInfo().hasXReleasePrefix(); }
497 :
498 : //! Tests whether the rep prefix is supported by the instruction, but ignored (has no effect).
499 : inline bool isRepIgnored() const noexcept { return commonInfo().isRepIgnored(); }
500 : //! Tests whether the instruction uses MIB.
501 : inline bool isMibOp() const noexcept { return hasFlag(InstFlags::kMib); }
502 : //! Tests whether the instruction uses VSIB.
503 : inline bool isVsibOp() const noexcept { return hasFlag(InstFlags::kVsib); }
504 : //! Tests whether the instruction uses VEX (can be set together with EVEX if both are encodable).
505 : inline bool isVex() const noexcept { return hasFlag(InstFlags::kVex); }
506 : //! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable).
507 : inline bool isEvex() const noexcept { return hasFlag(InstFlags::kEvex); }
508 : //! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable).
509 : inline bool isVexOrEvex() const noexcept { return hasFlag(InstFlags::kVex | InstFlags::kEvex); }
510 :
511 : inline bool isEvexCompatible() const noexcept { return hasFlag(InstFlags::kEvexCompat); }
512 : inline bool isEvexKRegOnly() const noexcept { return hasFlag(InstFlags::kEvexKReg); }
513 : inline bool isEvexTwoOpOnly() const noexcept { return hasFlag(InstFlags::kEvexTwoOp); }
514 : inline bool isEvexTransformable() const noexcept { return hasFlag(InstFlags::kEvexTransformable); }
515 :
516 : //! Tests whether the instruction supports AVX512 masking {k}.
517 : inline bool hasAvx512K() const noexcept { return hasAvx512Flag(Avx512Flags::kK); }
518 : //! Tests whether the instruction supports AVX512 zeroing {k}{z}.
519 : inline bool hasAvx512Z() const noexcept { return hasAvx512Flag(Avx512Flags::kZ); }
520 : //! Tests whether the instruction supports AVX512 embedded-rounding {er}.
521 : inline bool hasAvx512ER() const noexcept { return hasAvx512Flag(Avx512Flags::kER); }
522 : //! Tests whether the instruction supports AVX512 suppress-all-exceptions {sae}.
523 : inline bool hasAvx512SAE() const noexcept { return hasAvx512Flag(Avx512Flags::kSAE); }
524 : //! Tests whether the instruction supports AVX512 broadcast (either 32-bit or 64-bit).
525 : inline bool hasAvx512B() const noexcept { return hasAvx512Flag(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64); }
526 : //! Tests whether the instruction supports AVX512 broadcast (16-bit).
527 : inline bool hasAvx512B16() const noexcept { return hasAvx512Flag(Avx512Flags::kB16); }
528 : //! Tests whether the instruction supports AVX512 broadcast (32-bit).
529 : inline bool hasAvx512B32() const noexcept { return hasAvx512Flag(Avx512Flags::kB32); }
530 : //! Tests whether the instruction supports AVX512 broadcast (64-bit).
531 : inline bool hasAvx512B64() const noexcept { return hasAvx512Flag(Avx512Flags::kB64); }
532 :
533 : //! Returns a control flow category of the instruction.
534 : inline InstControlFlow controlFlow() const noexcept { return commonInfo().controlFlow(); }
535 : //! Returns a hint that can be used when both inputs are the same register.
536 : inline InstSameRegHint sameRegHint() const noexcept { return commonInfo().sameRegHint(); }
537 :
538 : inline uint32_t signatureIndex() const noexcept { return commonInfo().signatureIndex(); }
539 : inline uint32_t signatureCount() const noexcept { return commonInfo().signatureCount(); }
540 :
541 : inline const InstSignature* signatureData() const noexcept { return commonInfo().signatureData(); }
542 : inline const InstSignature* signatureEnd() const noexcept { return commonInfo().signatureEnd(); }
543 :
544 : //! \}
545 : };
546 :
547 : ASMJIT_VARAPI const InstInfo _instInfoTable[];
548 :
549 : static inline const InstInfo& infoById(InstId instId) noexcept {
550 : ASMJIT_ASSERT(Inst::isDefinedId(instId));
551 : return _instInfoTable[instId];
552 : }
553 :
554 : //! \cond INTERNAL
555 : static_assert(sizeof(OpSignature) == 8, "InstDB::OpSignature must be 8 bytes long");
556 : //! \endcond
557 :
558 : } // {InstDB}
559 :
560 : //! \}
561 :
562 : ASMJIT_END_SUB_NAMESPACE
563 :
564 : #endif // ASMJIT_X86_X86INSTDB_H_INCLUDED
565 :
566 : #endif // __PLUMED_HAS_ASMJIT
|