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_CORE_INST_H_INCLUDED
8 : #define ASMJIT_CORE_INST_H_INCLUDED
9 :
10 : #include "cpuinfo.h"
11 : #include "operand.h"
12 : #include "moved_string.h"
13 : #include "support.h"
14 :
15 : ASMJIT_BEGIN_NAMESPACE
16 :
17 : //! \addtogroup asmjit_instruction_db
18 : //! \{
19 :
20 : //! Describes an instruction id and modifiers used together with the id.
21 : //!
22 : //! Each architecture has a set of valid instructions indexed from 0. Instruction with 0 id is, however, a special
23 : //! instruction that describes a "no instruction" or "invalid instruction". Different architectures can assign a.
24 : //! different instruction to the same id, each architecture typicall has its own instructions indexed from 1.
25 : //!
26 : //! Instruction identifiers listed by architecture:
27 : //!
28 : //! - \ref x86::Inst (X86 and X86_64)
29 : //! - \ref a64::Inst (AArch64)
30 : typedef uint32_t InstId;
31 :
32 : //! Instruction id parts.
33 : //!
34 : //! A mask that specifies a bit-layout of \ref InstId.
35 : enum class InstIdParts : uint32_t {
36 : // Common Masks
37 : // ------------
38 :
39 : //! Real id without any modifiers (always 16 least significant bits).
40 : kRealId = 0x0000FFFFu,
41 : //! Instruction is abstract (or virtual, IR, etc...).
42 : kAbstract = 0x80000000u,
43 :
44 : // ARM Specific
45 : // ------------
46 :
47 : //! AArch32 first data type, used by ASIMD instructions (`inst.dt.dt2`).
48 : kA32_DT = 0x000F0000u,
49 : //! AArch32 second data type, used by ASIMD instructions (`inst.dt.dt2`).
50 : kA32_DT2 = 0x00F00000u,
51 : //! AArch32/AArch64 condition code.
52 : kARM_Cond = 0x78000000u
53 : };
54 :
55 : //! Instruction options.
56 : //!
57 : //! Instruction options complement instruction identifier and attributes.
58 : enum class InstOptions : uint32_t {
59 : //! No options.
60 : kNone = 0,
61 :
62 : //! Used internally by emitters for handling errors and rare cases.
63 : kReserved = 0x00000001u,
64 :
65 : //! Prevents following a jump during compilation (Compiler).
66 : kUnfollow = 0x00000002u,
67 :
68 : //! Overwrite the destination operand(s) (Compiler).
69 : //!
70 : //! Hint that is important for register liveness analysis. It tells the compiler that the destination operand will
71 : //! be overwritten now or by adjacent instructions. Compiler knows when a register is completely overwritten by a
72 : //! single instruction, for example you don't have to mark "movaps" or "pxor x, x", however, if a pair of
73 : //! instructions is used and the first of them doesn't completely overwrite the content of the destination,
74 : //! Compiler fails to mark that register as dead.
75 : //!
76 : //! X86 Specific
77 : //! ------------
78 : //!
79 : //! - All instructions that always overwrite at least the size of the register the virtual-register uses, for
80 : //! example "mov", "movq", "movaps" don't need the overwrite option to be used - conversion, shuffle, and
81 : //! other miscellaneous instructions included.
82 : //!
83 : //! - All instructions that clear the destination register if all operands are the same, for example "xor x, x",
84 : //! "pcmpeqb x x", etc...
85 : //!
86 : //! - Consecutive instructions that partially overwrite the variable until there is no old content require
87 : //! `BaseCompiler::overwrite()` to be used. Some examples (not always the best use cases thought):
88 : //!
89 : //! - `movlps xmm0, ?` followed by `movhps xmm0, ?` and vice versa
90 : //! - `movlpd xmm0, ?` followed by `movhpd xmm0, ?` and vice versa
91 : //! - `mov al, ?` followed by `and ax, 0xFF`
92 : //! - `mov al, ?` followed by `mov ah, al`
93 : //! - `pinsrq xmm0, ?, 0` followed by `pinsrq xmm0, ?, 1`
94 : //!
95 : //! - If the allocated virtual register is used temporarily for scalar operations. For example if you allocate a
96 : //! full vector like `x86::Compiler::newXmm()` and then use that vector for scalar operations you should use
97 : //! `overwrite()` directive:
98 : //!
99 : //! - `sqrtss x, y` - only LO element of `x` is changed, if you don't
100 : //! use HI elements, use `compiler.overwrite().sqrtss(x, y)`.
101 : kOverwrite = 0x00000004u,
102 :
103 : //! Emit short-form of the instruction.
104 : kShortForm = 0x00000010u,
105 : //! Emit long-form of the instruction.
106 : kLongForm = 0x00000020u,
107 :
108 : //! Conditional jump is likely to be taken.
109 : kTaken = 0x00000040u,
110 : //! Conditional jump is unlikely to be taken.
111 : kNotTaken = 0x00000080u,
112 :
113 : // X86 & X64 Options
114 : // -----------------
115 :
116 : //! Use ModMR instead of ModRM if applicable.
117 : kX86_ModMR = 0x00000100u,
118 : //! Use ModRM instead of ModMR if applicable.
119 : kX86_ModRM = 0x00000200u,
120 : //! Use 3-byte VEX prefix if possible (AVX) (must be 0x00000400).
121 : kX86_Vex3 = 0x00000400u,
122 : //! Use VEX prefix when both VEX|EVEX prefixes are available (HINT: AVX_VNNI).
123 : kX86_Vex = 0x00000800u,
124 : //! Use 4-byte EVEX prefix if possible (AVX-512) (must be 0x00001000).
125 : kX86_Evex = 0x00001000u,
126 :
127 : //! LOCK prefix (lock-enabled instructions only).
128 : kX86_Lock = 0x00002000u,
129 : //! REP prefix (string instructions only).
130 : kX86_Rep = 0x00004000u,
131 : //! REPNE prefix (string instructions only).
132 : kX86_Repne = 0x00008000u,
133 :
134 : //! XACQUIRE prefix (only allowed instructions).
135 : kX86_XAcquire = 0x00010000u,
136 : //! XRELEASE prefix (only allowed instructions).
137 : kX86_XRelease = 0x00020000u,
138 :
139 : //! AVX-512: embedded-rounding {er} and implicit {sae}.
140 : kX86_ER = 0x00040000u,
141 : //! AVX-512: suppress-all-exceptions {sae}.
142 : kX86_SAE = 0x00080000u,
143 : //! AVX-512: round-to-nearest (even) {rn-sae} (bits 00).
144 : kX86_RN_SAE = 0x00000000u,
145 : //! AVX-512: round-down (toward -inf) {rd-sae} (bits 01).
146 : kX86_RD_SAE = 0x00200000u,
147 : //! AVX-512: round-up (toward +inf) {ru-sae} (bits 10).
148 : kX86_RU_SAE = 0x00400000u,
149 : //! AVX-512: round-toward-zero (truncate) {rz-sae} (bits 11).
150 : kX86_RZ_SAE = 0x00600000u,
151 : //! AVX-512: Use zeroing {k}{z} instead of merging {k}.
152 : kX86_ZMask = 0x00800000u,
153 :
154 : //! AVX-512: Mask to get embedded rounding bits (2 bits).
155 : kX86_ERMask = kX86_RZ_SAE,
156 : //! AVX-512: Mask of all possible AVX-512 options except EVEX prefix flag.
157 : kX86_AVX512Mask = 0x00FC0000u,
158 :
159 : //! Force REX.B and/or VEX.B field (X64 only).
160 : kX86_OpCodeB = 0x01000000u,
161 : //! Force REX.X and/or VEX.X field (X64 only).
162 : kX86_OpCodeX = 0x02000000u,
163 : //! Force REX.R and/or VEX.R field (X64 only).
164 : kX86_OpCodeR = 0x04000000u,
165 : //! Force REX.W and/or VEX.W field (X64 only).
166 : kX86_OpCodeW = 0x08000000u,
167 : //! Force REX prefix (X64 only).
168 : kX86_Rex = 0x40000000u,
169 : //! Invalid REX prefix (set by X86 or when AH|BH|CH|DH regs are used on X64).
170 : kX86_InvalidRex = 0x80000000u
171 : };
172 1140989 : ASMJIT_DEFINE_ENUM_FLAGS(InstOptions)
173 :
174 : //! Instruction control flow.
175 : enum class InstControlFlow : uint32_t {
176 : //! Regular instruction.
177 : kRegular = 0u,
178 : //! Unconditional jump.
179 : kJump = 1u,
180 : //! Conditional jump (branch).
181 : kBranch = 2u,
182 : //! Function call.
183 : kCall = 3u,
184 : //! Function return.
185 : kReturn = 4u,
186 :
187 : //! Maximum value of `InstType`.
188 : kMaxValue = kReturn
189 : };
190 :
191 : //! Hint that is used when both input operands to the instruction are the same.
192 : //!
193 : //! Provides hints to the instrution RW query regarding special cases in which two or more operands are the same
194 : //! registers. This is required by instructions such as XOR, AND, OR, SUB, etc... These hints will influence the
195 : //! RW operations query.
196 : enum class InstSameRegHint : uint8_t {
197 : //! No special handling.
198 : kNone = 0,
199 : //! Operands become read-only, the operation doesn't change the content - `X & X` and similar.
200 : kRO = 1,
201 : //! Operands become write-only, the content of the input(s) don't matter - `X ^ X`, `X - X`, and similar.
202 : kWO = 2
203 : };
204 :
205 : //! Instruction id, options, and extraReg in a single structure. This structure exists mainly to simplify analysis
206 : //! and validation API that requires `BaseInst` and `Operand[]` array.
207 : class BaseInst {
208 : public:
209 : //! \name Members
210 : //! \{
211 :
212 : //! Instruction id with modifiers.
213 : InstId _id;
214 : //! Instruction options.
215 : InstOptions _options;
216 : //! Extra register used by the instruction (either REP register or AVX-512 selector).
217 : RegOnly _extraReg;
218 :
219 : enum Id : uint32_t {
220 : //! Invalid or uninitialized instruction id.
221 : kIdNone = 0x00000000u,
222 : //! Abstract instruction (BaseBuilder and BaseCompiler).
223 : kIdAbstract = 0x80000000u
224 : };
225 :
226 : //! \}
227 :
228 : //! \name Construction & Destruction
229 : //! \{
230 :
231 : //! Creates a new BaseInst instance with `id` and `options` set.
232 : //!
233 : //! Default values of `id` and `options` are zero, which means 'none' instruction. Such instruction is guaranteed
234 : //! to never exist for any architecture supported by AsmJit.
235 : inline explicit BaseInst(InstId instId = 0, InstOptions options = InstOptions::kNone) noexcept
236 419501 : : _id(instId),
237 419501 : _options(options),
238 419501 : _extraReg() {}
239 :
240 : inline BaseInst(InstId instId, InstOptions options, const RegOnly& extraReg) noexcept
241 0 : : _id(instId),
242 0 : _options(options),
243 0 : _extraReg(extraReg) {}
244 :
245 : inline BaseInst(InstId instId, InstOptions options, const BaseReg& extraReg) noexcept
246 : : _id(instId),
247 : _options(options),
248 : _extraReg { extraReg.signature(), extraReg.id() } {}
249 :
250 : //! \}
251 :
252 : //! \name Instruction id and modifiers
253 : //! \{
254 :
255 : //! Returns the instruction id with modifiers.
256 1116369 : inline InstId id() const noexcept { return _id; }
257 : //! Sets the instruction id and modiiers from `id`.
258 0 : inline void setId(InstId id) noexcept { _id = id; }
259 : //! Resets the instruction id and modifiers to zero, see \ref kIdNone.
260 : inline void resetId() noexcept { _id = 0; }
261 :
262 : //! Returns a real instruction id that doesn't contain any modifiers.
263 0 : inline InstId realId() const noexcept { return _id & uint32_t(InstIdParts::kRealId); }
264 :
265 : template<InstIdParts kPart>
266 : inline uint32_t getInstIdPart() const noexcept {
267 0 : return (uint32_t(_id) & uint32_t(kPart)) >> Support::ConstCTZ<uint32_t(kPart)>::value;
268 : }
269 :
270 : template<InstIdParts kPart>
271 : inline void setInstIdPart(uint32_t value) noexcept {
272 : _id = (_id & ~uint32_t(kPart)) | (value << Support::ConstCTZ<uint32_t(kPart)>::value);
273 : }
274 :
275 : //! \}
276 :
277 : //! \name Instruction Options
278 : //! \{
279 :
280 392009 : inline InstOptions options() const noexcept { return _options; }
281 0 : inline bool hasOption(InstOptions option) const noexcept { return Support::test(_options, option); }
282 : inline void setOptions(InstOptions options) noexcept { _options = options; }
283 : inline void addOptions(InstOptions options) noexcept { _options |= options; }
284 : inline void clearOptions(InstOptions options) noexcept { _options &= ~options; }
285 : inline void resetOptions() noexcept { _options = InstOptions::kNone; }
286 :
287 : //! \}
288 :
289 : //! \name Extra Register
290 : //! \{
291 :
292 : inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); }
293 : inline RegOnly& extraReg() noexcept { return _extraReg; }
294 : inline const RegOnly& extraReg() const noexcept { return _extraReg; }
295 : inline void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); }
296 : inline void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); }
297 : inline void resetExtraReg() noexcept { _extraReg.reset(); }
298 :
299 : //! \}
300 :
301 : //! \name ARM Specific
302 : //! \{
303 :
304 0 : inline arm::CondCode armCondCode() const noexcept { return (arm::CondCode)getInstIdPart<InstIdParts::kARM_Cond>(); }
305 : inline void setArmCondCode(arm::CondCode cc) noexcept { setInstIdPart<InstIdParts::kARM_Cond>(uint32_t(cc)); }
306 :
307 : //! \}
308 :
309 : //! \name Statics
310 : //! \{
311 :
312 : static inline constexpr InstId composeARMInstId(uint32_t id, arm::CondCode cc) noexcept {
313 0 : return id | (uint32_t(cc) << Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value);
314 : }
315 :
316 : static inline constexpr InstId extractRealId(uint32_t id) noexcept {
317 0 : return id & uint32_t(InstIdParts::kRealId);
318 : }
319 :
320 : static inline constexpr arm::CondCode extractARMCondCode(uint32_t id) noexcept {
321 0 : return (arm::CondCode)((uint32_t(id) & uint32_t(InstIdParts::kARM_Cond)) >> Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value);
322 : }
323 :
324 : //! \}
325 : };
326 :
327 : //! CPU read/write flags used by \ref InstRWInfo.
328 : //!
329 : //! These flags can be used to get a basic overview about CPU specifics flags used by instructions.
330 : enum class CpuRWFlags : uint32_t {
331 : //! No flags.
332 : kNone = 0x00000000u,
333 :
334 : // Common RW Flags (0x000000FF)
335 : // ----------------------------
336 :
337 : //! Carry flag.
338 : kCF = 0x00000001u,
339 : //! Signed overflow flag.
340 : kOF = 0x00000002u,
341 : //! Sign flag (negative/sign, if set).
342 : kSF = 0x00000004u,
343 : //! Zero and/or equality flag (1 if zero/equal).
344 : kZF = 0x00000008u,
345 :
346 : // X86 Specific RW Flags (0xFFFFFF00)
347 : // ----------------------------------
348 :
349 : //! Carry flag (X86, X86_64).
350 : kX86_CF = kCF,
351 : //! Overflow flag (X86, X86_64).
352 : kX86_OF = kOF,
353 : //! Sign flag (X86, X86_64).
354 : kX86_SF = kSF,
355 : //! Zero flag (X86, X86_64).
356 : kX86_ZF = kZF,
357 :
358 : //! Adjust flag (X86, X86_64).
359 : kX86_AF = 0x00000100u,
360 : //! Parity flag (X86, X86_64).
361 : kX86_PF = 0x00000200u,
362 : //! Direction flag (X86, X86_64).
363 : kX86_DF = 0x00000400u,
364 : //! Interrupt enable flag (X86, X86_64).
365 : kX86_IF = 0x00000800u,
366 :
367 : //! Alignment check flag (X86, X86_64).
368 : kX86_AC = 0x00001000u,
369 :
370 : //! FPU C0 status flag (X86, X86_64).
371 : kX86_C0 = 0x00010000u,
372 : //! FPU C1 status flag (X86, X86_64).
373 : kX86_C1 = 0x00020000u,
374 : //! FPU C2 status flag (X86, X86_64).
375 : kX86_C2 = 0x00040000u,
376 : //! FPU C3 status flag (X86, X86_64).
377 : kX86_C3 = 0x00080000u
378 : };
379 : ASMJIT_DEFINE_ENUM_FLAGS(CpuRWFlags)
380 :
381 : //! Operand read/write flags describe how the operand is accessed and some additional features.
382 : enum class OpRWFlags {
383 : //! No flags.
384 : kNone = 0,
385 :
386 : //! Operand is read.
387 : kRead = 0x00000001u,
388 :
389 : //! Operand is written.
390 : kWrite = 0x00000002u,
391 :
392 : //! Operand is both read and written.
393 : kRW = 0x00000003u,
394 :
395 : //! Register operand can be replaced by a memory operand.
396 : kRegMem = 0x00000004u,
397 :
398 : //! The register must be allocated to the index of the previous register + 1.
399 : //!
400 : //! This flag is used by all architectures to describe instructions that use consecutive registers, where only the
401 : //! first one is encoded in the instruction, and the others are just a sequence that starts with the first one. On
402 : //! X86/X86_64 architecture this is used by instructions such as V4FMADDPS, V4FMADDSS, V4FNMADDPS, V4FNMADDSS,
403 : //! VP4DPWSSD, VP4DPWSSDS, VP2INTERSECTD, and VP2INTERSECTQ. On ARM/AArch64 this is used by vector load and store
404 : //! instructions that can load or store multiple registers at once.
405 : kConsecutive = 0x00000008u,
406 :
407 : //! The `extendByteMask()` represents a zero extension.
408 : kZExt = 0x00000010u,
409 :
410 : //! Register operand must use \ref OpRWInfo::physId().
411 : kRegPhysId = 0x00000100u,
412 : //! Base register of a memory operand must use \ref OpRWInfo::physId().
413 : kMemPhysId = 0x00000200u,
414 :
415 : //! This memory operand is only used to encode registers and doesn't access memory.
416 : //!
417 : //! X86 Specific
418 : //! ------------
419 : //!
420 : //! Instructions that use such feature include BNDLDX, BNDSTX, and LEA.
421 : kMemFake = 0x000000400u,
422 :
423 : //! Base register of the memory operand will be read.
424 : kMemBaseRead = 0x00001000u,
425 : //! Base register of the memory operand will be written.
426 : kMemBaseWrite = 0x00002000u,
427 : //! Base register of the memory operand will be read & written.
428 : kMemBaseRW = 0x00003000u,
429 :
430 : //! Index register of the memory operand will be read.
431 : kMemIndexRead = 0x00004000u,
432 : //! Index register of the memory operand will be written.
433 : kMemIndexWrite = 0x00008000u,
434 : //! Index register of the memory operand will be read & written.
435 : kMemIndexRW = 0x0000C000u,
436 :
437 : //! Base register of the memory operand will be modified before the operation.
438 : kMemBasePreModify = 0x00010000u,
439 : //! Base register of the memory operand will be modified after the operation.
440 : kMemBasePostModify = 0x00020000u
441 : };
442 1247851 : ASMJIT_DEFINE_ENUM_FLAGS(OpRWFlags)
443 :
444 : // Don't remove these asserts. Read/Write flags are used extensively
445 : // by Compiler and they must always be compatible with constants below.
446 : static_assert(uint32_t(OpRWFlags::kRead) == 0x1, "OpRWFlags::kRead flag must be 0x1");
447 : static_assert(uint32_t(OpRWFlags::kWrite) == 0x2, "OpRWFlags::kWrite flag must be 0x2");
448 : static_assert(uint32_t(OpRWFlags::kRegMem) == 0x4, "OpRWFlags::kRegMem flag must be 0x4");
449 :
450 : //! Read/Write information related to a single operand, used by \ref InstRWInfo.
451 : struct OpRWInfo {
452 : //! \name Members
453 : //! \{
454 :
455 : //! Read/Write flags.
456 : OpRWFlags _opFlags;
457 : //! Physical register index, if required.
458 : uint8_t _physId;
459 : //! Size of a possible memory operand that can replace a register operand.
460 : uint8_t _rmSize;
461 : //! If non-zero, then this is a consecutive lead register, and the value describes how many registers follow.
462 : uint8_t _consecutiveLeadCount;
463 : //! Reserved for future use.
464 : uint8_t _reserved[1];
465 : //! Read bit-mask where each bit represents one byte read from Reg/Mem.
466 : uint64_t _readByteMask;
467 : //! Write bit-mask where each bit represents one byte written to Reg/Mem.
468 : uint64_t _writeByteMask;
469 : //! Zero/Sign extend bit-mask where each bit represents one byte written to Reg/Mem.
470 : uint64_t _extendByteMask;
471 :
472 : //! \}
473 :
474 : //! \name Reset
475 : //! \{
476 :
477 : //! Resets this operand information to all zeros.
478 394528 : inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
479 :
480 : //! Resets this operand info (resets all members) and set common information
481 : //! to the given `opFlags`, `regSize`, and possibly `physId`.
482 : inline void reset(OpRWFlags opFlags, uint32_t regSize, uint32_t physId = BaseReg::kIdBad) noexcept {
483 88236 : _opFlags = opFlags;
484 88236 : _physId = uint8_t(physId);
485 88236 : _rmSize = Support::test(opFlags, OpRWFlags::kRegMem) ? uint8_t(regSize) : uint8_t(0);
486 88236 : _consecutiveLeadCount = 0;
487 : _resetReserved();
488 :
489 : uint64_t mask = Support::lsbMask<uint64_t>(regSize);
490 88236 : _readByteMask = Support::test(opFlags, OpRWFlags::kRead) ? mask : uint64_t(0);
491 88236 : _writeByteMask = Support::test(opFlags, OpRWFlags::kWrite) ? mask : uint64_t(0);
492 88236 : _extendByteMask = 0;
493 0 : }
494 :
495 : inline void _resetReserved() noexcept {
496 646381 : _reserved[0] = 0;
497 : }
498 :
499 : //! \}
500 :
501 : //! \name Operand Flags
502 : //! \{
503 :
504 : //! Returns operand flags.
505 646381 : inline OpRWFlags opFlags() const noexcept { return _opFlags; }
506 : //! Tests whether operand flags contain the given `flag`.
507 1062578 : inline bool hasOpFlag(OpRWFlags flag) const noexcept { return Support::test(_opFlags, flag); }
508 :
509 : //! Adds the given `flags` to operand flags.
510 70974 : inline void addOpFlags(OpRWFlags flags) noexcept { _opFlags |= flags; }
511 : //! Removes the given `flags` from operand flags.
512 : inline void clearOpFlags(OpRWFlags flags) noexcept { _opFlags &= ~flags; }
513 :
514 : //! Tests whether this operand is read from.
515 : inline bool isRead() const noexcept { return hasOpFlag(OpRWFlags::kRead); }
516 : //! Tests whether this operand is written to.
517 : inline bool isWrite() const noexcept { return hasOpFlag(OpRWFlags::kWrite); }
518 : //! Tests whether this operand is both read and write.
519 : inline bool isReadWrite() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRW; }
520 : //! Tests whether this operand is read only.
521 : inline bool isReadOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRead; }
522 : //! Tests whether this operand is write only.
523 : inline bool isWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kWrite; }
524 :
525 : //! Returns the type of a lead register, which is followed by consecutive registers.
526 575407 : inline uint32_t consecutiveLeadCount() const noexcept { return _consecutiveLeadCount; }
527 :
528 : //! Tests whether this operand is Reg/Mem
529 : //!
530 : //! Reg/Mem operands can use either register or memory.
531 : inline bool isRm() const noexcept { return hasOpFlag(OpRWFlags::kRegMem); }
532 :
533 : //! Tests whether the operand will be zero extended.
534 : inline bool isZExt() const noexcept { return hasOpFlag(OpRWFlags::kZExt); }
535 :
536 : //! \}
537 :
538 : //! \name Memory Flags
539 : //! \{
540 :
541 : //! Tests whether this is a fake memory operand, which is only used, because of encoding. Fake memory operands do
542 : //! not access any memory, they are only used to encode registers.
543 : inline bool isMemFake() const noexcept { return hasOpFlag(OpRWFlags::kMemFake); }
544 :
545 : //! Tests whether the instruction's memory BASE register is used.
546 : inline bool isMemBaseUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRW); }
547 : //! Tests whether the instruction reads from its BASE registers.
548 : inline bool isMemBaseRead() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRead); }
549 : //! Tests whether the instruction writes to its BASE registers.
550 : inline bool isMemBaseWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseWrite); }
551 : //! Tests whether the instruction reads and writes from/to its BASE registers.
552 : inline bool isMemBaseReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRW; }
553 : //! Tests whether the instruction only reads from its BASE registers.
554 : inline bool isMemBaseReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRead; }
555 : //! Tests whether the instruction only writes to its BASE registers.
556 : inline bool isMemBaseWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseWrite; }
557 :
558 : //! Tests whether the instruction modifies the BASE register before it uses it to calculate the target address.
559 : inline bool isMemBasePreModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePreModify); }
560 : //! Tests whether the instruction modifies the BASE register after it uses it to calculate the target address.
561 : inline bool isMemBasePostModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePostModify); }
562 :
563 : //! Tests whether the instruction's memory INDEX register is used.
564 : inline bool isMemIndexUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRW); }
565 : //! Tests whether the instruction reads the INDEX registers.
566 : inline bool isMemIndexRead() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRead); }
567 : //! Tests whether the instruction writes to its INDEX registers.
568 : inline bool isMemIndexWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexWrite); }
569 : //! Tests whether the instruction reads and writes from/to its INDEX registers.
570 : inline bool isMemIndexReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRW; }
571 : //! Tests whether the instruction only reads from its INDEX registers.
572 : inline bool isMemIndexReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRead; }
573 : //! Tests whether the instruction only writes to its INDEX registers.
574 : inline bool isMemIndexWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexWrite; }
575 :
576 : //! \}
577 :
578 : //! \name Physical Register ID
579 : //! \{
580 :
581 : //! Returns a physical id of the register that is fixed for this operand.
582 : //!
583 : //! Returns \ref BaseReg::kIdBad if any register can be used.
584 0 : inline uint32_t physId() const noexcept { return _physId; }
585 : //! Tests whether \ref physId() would return a valid physical register id.
586 : inline bool hasPhysId() const noexcept { return _physId != BaseReg::kIdBad; }
587 : //! Sets physical register id, which would be fixed for this operand.
588 : inline void setPhysId(uint32_t physId) noexcept { _physId = uint8_t(physId); }
589 :
590 : //! \}
591 :
592 : //! \name Reg/Mem Information
593 : //! \{
594 :
595 : //! Returns Reg/Mem size of the operand.
596 575407 : inline uint32_t rmSize() const noexcept { return _rmSize; }
597 : //! Sets Reg/Mem size of the operand.
598 114299 : inline void setRmSize(uint32_t rmSize) noexcept { _rmSize = uint8_t(rmSize); }
599 :
600 : //! \}
601 :
602 : //! \name Read & Write Masks
603 : //! \{
604 :
605 : //! Returns read mask.
606 : inline uint64_t readByteMask() const noexcept { return _readByteMask; }
607 : //! Returns write mask.
608 0 : inline uint64_t writeByteMask() const noexcept { return _writeByteMask; }
609 : //! Returns extend mask.
610 294583 : inline uint64_t extendByteMask() const noexcept { return _extendByteMask; }
611 :
612 : //! Sets read mask.
613 0 : inline void setReadByteMask(uint64_t mask) noexcept { _readByteMask = mask; }
614 : //! Sets write mask.
615 0 : inline void setWriteByteMask(uint64_t mask) noexcept { _writeByteMask = mask; }
616 : //! Sets externd mask.
617 206347 : inline void setExtendByteMask(uint64_t mask) noexcept { _extendByteMask = mask; }
618 :
619 : //! \}
620 : };
621 :
622 : //! Flags used by \ref InstRWInfo.
623 : enum class InstRWFlags : uint32_t {
624 : //! No flags.
625 : kNone = 0x00000000u,
626 :
627 : //! Describes a move operation.
628 : //!
629 : //! This flag is used by RA to eliminate moves that are guaranteed to be moves only.
630 : kMovOp = 0x00000001u
631 : };
632 159210 : ASMJIT_DEFINE_ENUM_FLAGS(InstRWFlags)
633 :
634 : //! Read/Write information of an instruction.
635 : struct InstRWInfo {
636 : //! \name Members
637 : //! \{
638 :
639 : //! Instruction flags (there are no flags at the moment, this field is reserved).
640 : InstRWFlags _instFlags;
641 : //! CPU flags read.
642 : CpuRWFlags _readFlags;
643 : //! CPU flags written.
644 : CpuRWFlags _writeFlags;
645 : //! Count of operands.
646 : uint8_t _opCount;
647 : //! CPU feature required for replacing register operand with memory operand.
648 : uint8_t _rmFeature;
649 : //! Reserved for future use.
650 : uint8_t _reserved[18];
651 : //! Read/Write onfo of extra register (rep{} or kz{}).
652 : OpRWInfo _extraReg;
653 : //! Read/Write info of instruction operands.
654 : OpRWInfo _operands[Globals::kMaxOpCount];
655 :
656 : //! \}
657 :
658 : //! \name Commons
659 : //! \{
660 :
661 : //! Resets this RW information to all zeros.
662 : inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
663 :
664 : //! \}
665 :
666 : //! \name Instruction Flags
667 : //! \{
668 :
669 : //! Returns flags associated with the instruction, see \ref InstRWFlags.
670 304316 : inline InstRWFlags instFlags() const noexcept { return _instFlags; }
671 :
672 : //! Tests whether the instruction flags contain `flag`.
673 520396 : inline bool hasInstFlag(InstRWFlags flag) const noexcept { return Support::test(_instFlags, flag); }
674 :
675 : //! Tests whether the instruction flags contain \ref InstRWFlags::kMovOp.
676 : inline bool isMovOp() const noexcept { return hasInstFlag(InstRWFlags::kMovOp); }
677 :
678 : //! \}
679 :
680 : //! \name CPU Flags Information
681 : //! \{
682 :
683 : //! Returns a mask of CPU flags read.
684 : inline CpuRWFlags readFlags() const noexcept { return _readFlags; }
685 : //! Returns a mask of CPU flags written.
686 : inline CpuRWFlags writeFlags() const noexcept { return _writeFlags; }
687 :
688 : //! \}
689 :
690 : //! \name Reg/Mem Information
691 : //! \{
692 :
693 : //! Returns the CPU feature required to replace a register operand with memory operand. If the returned feature is
694 : //! zero (none) then this instruction either doesn't provide memory operand combination or there is no extra CPU
695 : //! feature required.
696 : //!
697 : //! X86 Specific
698 : //! ------------
699 : //!
700 : //! Some AVX+ instructions may require extra features for replacing registers with memory operands, for example
701 : //! VPSLLDQ instruction only supports `vpslldq reg, reg, imm` combination on AVX/AVX2 capable CPUs and requires
702 : //! AVX-512 for `vpslldq reg, mem, imm` combination.
703 575407 : inline uint32_t rmFeature() const noexcept { return _rmFeature; }
704 :
705 : //! \}
706 :
707 : //! \name Operand Read/Write Information
708 : //! \{
709 :
710 : //! Returns RW information of extra register operand (extraReg).
711 : inline const OpRWInfo& extraReg() const noexcept { return _extraReg; }
712 :
713 : //! Returns RW information of all instruction's operands.
714 : inline const OpRWInfo* operands() const noexcept { return _operands; }
715 :
716 : //! Returns RW information of the operand at the given `index`.
717 : inline const OpRWInfo& operand(size_t index) const noexcept {
718 : ASMJIT_ASSERT(index < Globals::kMaxOpCount);
719 : return _operands[index];
720 : }
721 :
722 : //! Returns the number of operands this instruction has.
723 0 : inline uint32_t opCount() const noexcept { return _opCount; }
724 :
725 : //! \}
726 : };
727 :
728 : //! Validation flags that can be used with \ref InstAPI::validate().
729 : enum class ValidationFlags : uint32_t {
730 : //! No flags.
731 : kNone = 0,
732 : //! Allow virtual registers in the instruction.
733 : kEnableVirtRegs = 0x01u
734 : };
735 0 : ASMJIT_DEFINE_ENUM_FLAGS(ValidationFlags)
736 :
737 : //! Instruction API.
738 : namespace InstAPI {
739 :
740 : #ifndef ASMJIT_NO_TEXT
741 : //! Appends the name of the instruction specified by `instId` and `instOptions` into the `output` string.
742 : //!
743 : //! \note Instruction options would only affect instruction prefix & suffix, other options would be ignored.
744 : //! If `instOptions` is zero then only raw instruction name (without any additional text) will be appended.
745 : ASMJIT_API Error instIdToString(Arch arch, InstId instId, String& output) noexcept;
746 :
747 : //! Parses an instruction name in the given string `s`. Length is specified by `len` argument, which can be
748 : //! `SIZE_MAX` if `s` is known to be null terminated.
749 : //!
750 : //! Returns the parsed instruction id or \ref BaseInst::kIdNone if no such instruction exists.
751 : ASMJIT_API InstId stringToInstId(Arch arch, const char* s, size_t len) noexcept;
752 : #endif // !ASMJIT_NO_TEXT
753 :
754 : #ifndef ASMJIT_NO_VALIDATION
755 : //! Validates the given instruction considering the given `validationFlags`.
756 : ASMJIT_API Error validate(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, ValidationFlags validationFlags = ValidationFlags::kNone) noexcept;
757 : #endif // !ASMJIT_NO_VALIDATION
758 :
759 : #ifndef ASMJIT_NO_INTROSPECTION
760 : //! Gets Read/Write information of the given instruction.
761 : ASMJIT_API Error queryRWInfo(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, InstRWInfo* out) noexcept;
762 :
763 : //! Gets CPU features required by the given instruction.
764 : ASMJIT_API Error queryFeatures(Arch arch, const BaseInst& inst, const Operand_* operands, size_t opCount, CpuFeatures* out) noexcept;
765 : #endif // !ASMJIT_NO_INTROSPECTION
766 :
767 : } // {InstAPI}
768 :
769 : //! \}
770 :
771 : ASMJIT_END_NAMESPACE
772 :
773 : #endif // ASMJIT_CORE_INST_H_INCLUDED
774 :
775 : #endif // __PLUMED_HAS_ASMJIT
|