asmjit 0.2.0 → 0.2.1

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