asmjit 0.2.0 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (204) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/Rakefile +5 -3
  4. data/asmjit.gemspec +1 -3
  5. data/ext/asmjit/asmjit/.editorconfig +10 -0
  6. data/ext/asmjit/asmjit/.github/FUNDING.yml +1 -0
  7. data/ext/asmjit/asmjit/.github/workflows/build-config.json +47 -0
  8. data/ext/asmjit/asmjit/.github/workflows/build.yml +156 -0
  9. data/ext/asmjit/asmjit/.gitignore +6 -0
  10. data/ext/asmjit/asmjit/CMakeLists.txt +611 -0
  11. data/ext/asmjit/asmjit/LICENSE.md +17 -0
  12. data/ext/asmjit/asmjit/README.md +69 -0
  13. data/ext/asmjit/asmjit/src/asmjit/a64.h +62 -0
  14. data/ext/asmjit/asmjit/src/asmjit/arm/a64archtraits_p.h +81 -0
  15. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.cpp +5115 -0
  16. data/ext/asmjit/asmjit/src/asmjit/arm/a64assembler.h +72 -0
  17. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.cpp +51 -0
  18. data/ext/asmjit/asmjit/src/asmjit/arm/a64builder.h +57 -0
  19. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.cpp +60 -0
  20. data/ext/asmjit/asmjit/src/asmjit/arm/a64compiler.h +247 -0
  21. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper.cpp +464 -0
  22. data/ext/asmjit/asmjit/src/asmjit/arm/a64emithelper_p.h +50 -0
  23. data/ext/asmjit/asmjit/src/asmjit/arm/a64emitter.h +1228 -0
  24. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter.cpp +298 -0
  25. data/ext/asmjit/asmjit/src/asmjit/arm/a64formatter_p.h +59 -0
  26. data/ext/asmjit/asmjit/src/asmjit/arm/a64func.cpp +189 -0
  27. data/ext/asmjit/asmjit/src/asmjit/arm/a64func_p.h +33 -0
  28. data/ext/asmjit/asmjit/src/asmjit/arm/a64globals.h +1894 -0
  29. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi.cpp +278 -0
  30. data/ext/asmjit/asmjit/src/asmjit/arm/a64instapi_p.h +41 -0
  31. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.cpp +1957 -0
  32. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb.h +74 -0
  33. data/ext/asmjit/asmjit/src/asmjit/arm/a64instdb_p.h +876 -0
  34. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.cpp +85 -0
  35. data/ext/asmjit/asmjit/src/asmjit/arm/a64operand.h +312 -0
  36. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass.cpp +852 -0
  37. data/ext/asmjit/asmjit/src/asmjit/arm/a64rapass_p.h +105 -0
  38. data/ext/asmjit/asmjit/src/asmjit/arm/a64utils.h +179 -0
  39. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter.cpp +143 -0
  40. data/ext/asmjit/asmjit/src/asmjit/arm/armformatter_p.h +44 -0
  41. data/ext/asmjit/asmjit/src/asmjit/arm/armglobals.h +21 -0
  42. data/ext/asmjit/asmjit/src/asmjit/arm/armoperand.h +621 -0
  43. data/ext/asmjit/asmjit/src/asmjit/arm.h +62 -0
  44. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-begin.h +17 -0
  45. data/ext/asmjit/asmjit/src/asmjit/asmjit-scope-end.h +9 -0
  46. data/ext/asmjit/asmjit/src/asmjit/asmjit.h +33 -0
  47. data/ext/asmjit/asmjit/src/asmjit/core/api-build_p.h +55 -0
  48. data/ext/asmjit/asmjit/src/asmjit/core/api-config.h +613 -0
  49. data/ext/asmjit/asmjit/src/asmjit/core/archcommons.h +229 -0
  50. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.cpp +160 -0
  51. data/ext/asmjit/asmjit/src/asmjit/core/archtraits.h +290 -0
  52. data/ext/asmjit/asmjit/src/asmjit/core/assembler.cpp +406 -0
  53. data/ext/asmjit/asmjit/src/asmjit/core/assembler.h +129 -0
  54. data/ext/asmjit/asmjit/src/asmjit/core/builder.cpp +889 -0
  55. data/ext/asmjit/asmjit/src/asmjit/core/builder.h +1391 -0
  56. data/ext/asmjit/asmjit/src/asmjit/core/codebuffer.h +113 -0
  57. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.cpp +1149 -0
  58. data/ext/asmjit/asmjit/src/asmjit/core/codeholder.h +1035 -0
  59. data/ext/asmjit/asmjit/src/asmjit/core/codewriter.cpp +175 -0
  60. data/ext/asmjit/asmjit/src/asmjit/core/codewriter_p.h +179 -0
  61. data/ext/asmjit/asmjit/src/asmjit/core/compiler.cpp +582 -0
  62. data/ext/asmjit/asmjit/src/asmjit/core/compiler.h +737 -0
  63. data/ext/asmjit/asmjit/src/asmjit/core/compilerdefs.h +173 -0
  64. data/ext/asmjit/asmjit/src/asmjit/core/constpool.cpp +363 -0
  65. data/ext/asmjit/asmjit/src/asmjit/core/constpool.h +250 -0
  66. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.cpp +1162 -0
  67. data/ext/asmjit/asmjit/src/asmjit/core/cpuinfo.h +813 -0
  68. data/ext/asmjit/asmjit/src/asmjit/core/emithelper.cpp +323 -0
  69. data/ext/asmjit/asmjit/src/asmjit/core/emithelper_p.h +58 -0
  70. data/ext/asmjit/asmjit/src/asmjit/core/emitter.cpp +333 -0
  71. data/ext/asmjit/asmjit/src/asmjit/core/emitter.h +741 -0
  72. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils.cpp +129 -0
  73. data/ext/asmjit/asmjit/src/asmjit/core/emitterutils_p.h +89 -0
  74. data/ext/asmjit/asmjit/src/asmjit/core/environment.cpp +46 -0
  75. data/ext/asmjit/asmjit/src/asmjit/core/environment.h +508 -0
  76. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.cpp +14 -0
  77. data/ext/asmjit/asmjit/src/asmjit/core/errorhandler.h +228 -0
  78. data/ext/asmjit/asmjit/src/asmjit/core/formatter.cpp +584 -0
  79. data/ext/asmjit/asmjit/src/asmjit/core/formatter.h +247 -0
  80. data/ext/asmjit/asmjit/src/asmjit/core/formatter_p.h +34 -0
  81. data/ext/asmjit/asmjit/src/asmjit/core/func.cpp +286 -0
  82. data/ext/asmjit/asmjit/src/asmjit/core/func.h +1445 -0
  83. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext.cpp +293 -0
  84. data/ext/asmjit/asmjit/src/asmjit/core/funcargscontext_p.h +199 -0
  85. data/ext/asmjit/asmjit/src/asmjit/core/globals.cpp +133 -0
  86. data/ext/asmjit/asmjit/src/asmjit/core/globals.h +393 -0
  87. data/ext/asmjit/asmjit/src/asmjit/core/inst.cpp +113 -0
  88. data/ext/asmjit/asmjit/src/asmjit/core/inst.h +772 -0
  89. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.cpp +1242 -0
  90. data/ext/asmjit/asmjit/src/asmjit/core/jitallocator.h +261 -0
  91. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.cpp +80 -0
  92. data/ext/asmjit/asmjit/src/asmjit/core/jitruntime.h +89 -0
  93. data/ext/asmjit/asmjit/src/asmjit/core/logger.cpp +69 -0
  94. data/ext/asmjit/asmjit/src/asmjit/core/logger.h +198 -0
  95. data/ext/asmjit/asmjit/src/asmjit/core/misc_p.h +33 -0
  96. data/ext/asmjit/asmjit/src/asmjit/core/operand.cpp +132 -0
  97. data/ext/asmjit/asmjit/src/asmjit/core/operand.h +1611 -0
  98. data/ext/asmjit/asmjit/src/asmjit/core/osutils.cpp +84 -0
  99. data/ext/asmjit/asmjit/src/asmjit/core/osutils.h +61 -0
  100. data/ext/asmjit/asmjit/src/asmjit/core/osutils_p.h +68 -0
  101. data/ext/asmjit/asmjit/src/asmjit/core/raassignment_p.h +418 -0
  102. data/ext/asmjit/asmjit/src/asmjit/core/rabuilders_p.h +612 -0
  103. data/ext/asmjit/asmjit/src/asmjit/core/radefs_p.h +1204 -0
  104. data/ext/asmjit/asmjit/src/asmjit/core/ralocal.cpp +1166 -0
  105. data/ext/asmjit/asmjit/src/asmjit/core/ralocal_p.h +254 -0
  106. data/ext/asmjit/asmjit/src/asmjit/core/rapass.cpp +1969 -0
  107. data/ext/asmjit/asmjit/src/asmjit/core/rapass_p.h +1183 -0
  108. data/ext/asmjit/asmjit/src/asmjit/core/rastack.cpp +184 -0
  109. data/ext/asmjit/asmjit/src/asmjit/core/rastack_p.h +171 -0
  110. data/ext/asmjit/asmjit/src/asmjit/core/string.cpp +559 -0
  111. data/ext/asmjit/asmjit/src/asmjit/core/string.h +372 -0
  112. data/ext/asmjit/asmjit/src/asmjit/core/support.cpp +494 -0
  113. data/ext/asmjit/asmjit/src/asmjit/core/support.h +1773 -0
  114. data/ext/asmjit/asmjit/src/asmjit/core/target.cpp +14 -0
  115. data/ext/asmjit/asmjit/src/asmjit/core/target.h +53 -0
  116. data/ext/asmjit/asmjit/src/asmjit/core/type.cpp +74 -0
  117. data/ext/asmjit/asmjit/src/asmjit/core/type.h +419 -0
  118. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.cpp +722 -0
  119. data/ext/asmjit/asmjit/src/asmjit/core/virtmem.h +242 -0
  120. data/ext/asmjit/asmjit/src/asmjit/core/zone.cpp +353 -0
  121. data/ext/asmjit/asmjit/src/asmjit/core/zone.h +615 -0
  122. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.cpp +309 -0
  123. data/ext/asmjit/asmjit/src/asmjit/core/zonehash.h +186 -0
  124. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.cpp +163 -0
  125. data/ext/asmjit/asmjit/src/asmjit/core/zonelist.h +209 -0
  126. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.cpp +176 -0
  127. data/ext/asmjit/asmjit/src/asmjit/core/zonestack.h +239 -0
  128. data/ext/asmjit/asmjit/src/asmjit/core/zonestring.h +120 -0
  129. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.cpp +99 -0
  130. data/ext/asmjit/asmjit/src/asmjit/core/zonetree.h +380 -0
  131. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.cpp +356 -0
  132. data/ext/asmjit/asmjit/src/asmjit/core/zonevector.h +690 -0
  133. data/ext/asmjit/asmjit/src/asmjit/core.h +1861 -0
  134. data/ext/asmjit/asmjit/src/asmjit/x86/x86archtraits_p.h +148 -0
  135. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.cpp +5110 -0
  136. data/ext/asmjit/asmjit/src/asmjit/x86/x86assembler.h +685 -0
  137. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.cpp +52 -0
  138. data/ext/asmjit/asmjit/src/asmjit/x86/x86builder.h +351 -0
  139. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.cpp +61 -0
  140. data/ext/asmjit/asmjit/src/asmjit/x86/x86compiler.h +721 -0
  141. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper.cpp +619 -0
  142. data/ext/asmjit/asmjit/src/asmjit/x86/x86emithelper_p.h +60 -0
  143. data/ext/asmjit/asmjit/src/asmjit/x86/x86emitter.h +4315 -0
  144. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter.cpp +944 -0
  145. data/ext/asmjit/asmjit/src/asmjit/x86/x86formatter_p.h +58 -0
  146. data/ext/asmjit/asmjit/src/asmjit/x86/x86func.cpp +503 -0
  147. data/ext/asmjit/asmjit/src/asmjit/x86/x86func_p.h +33 -0
  148. data/ext/asmjit/asmjit/src/asmjit/x86/x86globals.h +2169 -0
  149. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi.cpp +1732 -0
  150. data/ext/asmjit/asmjit/src/asmjit/x86/x86instapi_p.h +41 -0
  151. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.cpp +4427 -0
  152. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb.h +563 -0
  153. data/ext/asmjit/asmjit/src/asmjit/x86/x86instdb_p.h +311 -0
  154. data/ext/asmjit/asmjit/src/asmjit/x86/x86opcode_p.h +436 -0
  155. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.cpp +231 -0
  156. data/ext/asmjit/asmjit/src/asmjit/x86/x86operand.h +1085 -0
  157. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass.cpp +1509 -0
  158. data/ext/asmjit/asmjit/src/asmjit/x86/x86rapass_p.h +94 -0
  159. data/ext/asmjit/asmjit/src/asmjit/x86.h +93 -0
  160. data/ext/asmjit/asmjit/src/asmjit.natvis +245 -0
  161. data/ext/asmjit/asmjit/test/asmjit_test_assembler.cpp +84 -0
  162. data/ext/asmjit/asmjit/test/asmjit_test_assembler.h +85 -0
  163. data/ext/asmjit/asmjit/test/asmjit_test_assembler_a64.cpp +4006 -0
  164. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x64.cpp +17833 -0
  165. data/ext/asmjit/asmjit/test/asmjit_test_assembler_x86.cpp +8300 -0
  166. data/ext/asmjit/asmjit/test/asmjit_test_compiler.cpp +253 -0
  167. data/ext/asmjit/asmjit/test/asmjit_test_compiler.h +73 -0
  168. data/ext/asmjit/asmjit/test/asmjit_test_compiler_a64.cpp +690 -0
  169. data/ext/asmjit/asmjit/test/asmjit_test_compiler_x86.cpp +4317 -0
  170. data/ext/asmjit/asmjit/test/asmjit_test_emitters.cpp +197 -0
  171. data/ext/asmjit/asmjit/test/asmjit_test_instinfo.cpp +181 -0
  172. data/ext/asmjit/asmjit/test/asmjit_test_misc.h +257 -0
  173. data/ext/asmjit/asmjit/test/asmjit_test_perf.cpp +62 -0
  174. data/ext/asmjit/asmjit/test/asmjit_test_perf.h +61 -0
  175. data/ext/asmjit/asmjit/test/asmjit_test_perf_a64.cpp +699 -0
  176. data/ext/asmjit/asmjit/test/asmjit_test_perf_x86.cpp +5032 -0
  177. data/ext/asmjit/asmjit/test/asmjit_test_unit.cpp +172 -0
  178. data/ext/asmjit/asmjit/test/asmjit_test_x86_sections.cpp +172 -0
  179. data/ext/asmjit/asmjit/test/asmjitutils.h +38 -0
  180. data/ext/asmjit/asmjit/test/broken.cpp +312 -0
  181. data/ext/asmjit/asmjit/test/broken.h +148 -0
  182. data/ext/asmjit/asmjit/test/cmdline.h +61 -0
  183. data/ext/asmjit/asmjit/test/performancetimer.h +41 -0
  184. data/ext/asmjit/asmjit/tools/configure-makefiles.sh +13 -0
  185. data/ext/asmjit/asmjit/tools/configure-ninja.sh +13 -0
  186. data/ext/asmjit/asmjit/tools/configure-sanitizers.sh +13 -0
  187. data/ext/asmjit/asmjit/tools/configure-vs2019-x64.bat +2 -0
  188. data/ext/asmjit/asmjit/tools/configure-vs2019-x86.bat +2 -0
  189. data/ext/asmjit/asmjit/tools/configure-vs2022-x64.bat +2 -0
  190. data/ext/asmjit/asmjit/tools/configure-vs2022-x86.bat +2 -0
  191. data/ext/asmjit/asmjit/tools/configure-xcode.sh +8 -0
  192. data/ext/asmjit/asmjit/tools/enumgen.js +417 -0
  193. data/ext/asmjit/asmjit/tools/enumgen.sh +3 -0
  194. data/ext/asmjit/asmjit/tools/tablegen-arm.js +365 -0
  195. data/ext/asmjit/asmjit/tools/tablegen-arm.sh +3 -0
  196. data/ext/asmjit/asmjit/tools/tablegen-x86.js +2638 -0
  197. data/ext/asmjit/asmjit/tools/tablegen-x86.sh +3 -0
  198. data/ext/asmjit/asmjit/tools/tablegen.js +947 -0
  199. data/ext/asmjit/asmjit/tools/tablegen.sh +4 -0
  200. data/ext/asmjit/asmjit.cc +167 -30
  201. data/ext/asmjit/extconf.rb +9 -9
  202. data/lib/asmjit/version.rb +1 -1
  203. data/lib/asmjit.rb +14 -4
  204. metadata +198 -17
@@ -0,0 +1,436 @@
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_X86_X86OPCODE_P_H_INCLUDED
7
+ #define ASMJIT_X86_X86OPCODE_P_H_INCLUDED
8
+
9
+ #include "../x86/x86globals.h"
10
+
11
+ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
12
+
13
+ //! \cond INTERNAL
14
+ //! \addtogroup asmjit_x86
15
+ //! \{
16
+
17
+ //! Helper class to store and manipulate X86 opcodes.
18
+ //!
19
+ //! The first 8 least significant bits describe the opcode byte as defined in ISA manuals, all other bits
20
+ //! describe other properties like prefixes, see `Opcode::Bits` for more information.
21
+ struct Opcode {
22
+ uint32_t v;
23
+
24
+ //! Describes a meaning of all bits of AsmJit's 32-bit opcode value.
25
+ //!
26
+ //! This schema is AsmJit specific and has been designed to allow encoding of all X86 instructions available. X86,
27
+ //! MMX, and SSE+ instructions always use `MM` and `PP` fields, which are encoded to corresponding prefixes needed
28
+ //! by X86 or SIMD instructions. AVX+ instructions embed `MMMMM` and `PP` fields in a VEX prefix, and AVX-512
29
+ //! instructions embed `MM` and `PP` in EVEX prefix.
30
+ //!
31
+ //! The instruction opcode definition uses 1 or 2 bytes as an opcode value. 1 byte is needed by most of the
32
+ //! instructions, 2 bytes are only used by legacy X87-FPU instructions. This means that a second byte is free to
33
+ //! by used by instructions encoded by using VEX and/or EVEX prefix.
34
+ //!
35
+ //! The fields description:
36
+ //!
37
+ //! - `MM` field is used to encode prefixes needed by the instruction or as a part of VEX/EVEX prefix. Described as
38
+ //! `mm` and `mmmmm` in instruction manuals.
39
+ //!
40
+ //! NOTE: Since `MM` field is defined as `mmmmm` (5 bits), but only 2 least significant bits are used by VEX and
41
+ //! EVEX prefixes, and additional 4th bit is used by XOP prefix, AsmJit uses the 3rd and 5th bit for it's own
42
+ //! purposes. These bits will probably never be used in future encodings as AVX512 uses only `000mm` from `mmmmm`.
43
+ //!
44
+ //! - `PP` field is used to encode prefixes needed by the instruction or as a part of VEX/EVEX prefix. Described as
45
+ //! `pp` in instruction manuals.
46
+ //!
47
+ //! - `LL` field is used exclusively by AVX+ and AVX512+ instruction sets. It describes vector size, which is `L.128`
48
+ //! for XMM register, `L.256` for for YMM register, and `L.512` for ZMM register. The `LL` field is omitted in case
49
+ //! that instruction supports multiple vector lengths, however, if the instruction requires specific `L` value it
50
+ //! must be specified as a part of the opcode.
51
+ //!
52
+ //! NOTE: `LL` having value `11` is not defined yet.
53
+ //!
54
+ //! - `W` field is the most complicated. It was added by 64-bit architecture to promote default operation width
55
+ //! (instructions that perform 32-bit operation by default require to override the width to 64-bit explicitly).
56
+ //! There is nothing wrong on this, however, some instructions introduced implicit `W` override, for example a
57
+ //! `cdqe` instruction is basically a `cwde` instruction with overridden `W` (set to 1). There are some others
58
+ //! in the base X86 instruction set. More recent instruction sets started using `W` field more often:
59
+ //!
60
+ //! - AVX instructions started using `W` field as an extended opcode for FMA, GATHER, PERM, and other instructions.
61
+ //! It also uses `W` field to override the default operation width in instructions like `vmovq`.
62
+ //!
63
+ //! - AVX-512 instructions started using `W` field as an extended opcode for all new instructions. This wouldn't
64
+ //! have been an issue if the `W` field of AVX-512 have matched AVX, but this is not always the case.
65
+ //!
66
+ //! - `O` field is an extended opcode field (3 bits) embedded in ModR/M BYTE.
67
+ //!
68
+ //! - `CDSHL` and `CDTT` fields describe 'compressed-displacement'. `CDSHL` is defined for each instruction that is
69
+ //! AVX-512 encodable (EVEX) and contains a base N shift (base shift to perform the calculation). The `CDTT` field
70
+ //! is derived from instruction specification and describes additional shift to calculate the final `CDSHL` that
71
+ //! will be used in SIB byte.
72
+ //!
73
+ //! \note Don't reorder any fields here, the shifts and masks were defined carefully to make encoding of X86
74
+ //! instructions fast, especially to construct REX, VEX, and EVEX prefixes in the most efficient way. Changing
75
+ //! values defined by these enums many cause AsmJit to emit invalid binary representations of instructions passed to
76
+ //! `x86::Assembler::_emit`.
77
+ enum Bits : uint32_t {
78
+ // MM & VEX & EVEX & XOP
79
+ // ---------------------
80
+ //
81
+ // Two meanings:
82
+ // * Part of a legacy opcode (prefixes emitted before the main opcode byte).
83
+ // * `MMMMM` field in VEX|EVEX|XOP instruction.
84
+ //
85
+ // AVX reserves 5 bits for `MMMMM` field, however AVX instructions only use 2 bits and XOP 3 bits. AVX-512 shrinks
86
+ // `MMMMM` field into `MMM` so it's safe to use [4:3] bits of `MMMMM` field for internal payload.
87
+ //
88
+ // AsmJit divides MMMMM field into this layout:
89
+ //
90
+ // [2:0] - Used to describe 0F, 0F38 and 0F3A legacy prefix bytes and 3 bits of MMMMM field for XOP/AVX/AVX512.
91
+ // [3] - Required by XOP instructions, so we use this bit also to indicate that this is a XOP opcode.
92
+ // [4] - Used to force EVEX prefix - this bit is not used by any X86 instruction yet, so AsmJit uses it to
93
+ // describe EVEX only instructions or sets its bit when user uses InstOptions::kX86_Evex to force EVEX.
94
+ kMM_Shift = 8,
95
+ kMM_Mask = 0x1Fu << kMM_Shift,
96
+ kMM_00 = 0x00u << kMM_Shift,
97
+ kMM_0F = 0x01u << kMM_Shift,
98
+ kMM_0F38 = 0x02u << kMM_Shift,
99
+ kMM_0F3A = 0x03u << kMM_Shift, // Described also as XOP.M3 in AMD manuals.
100
+ kMM_0F01 = 0x04u << kMM_Shift, // AsmJit way to describe 0F01 (never VEX/EVEX).
101
+
102
+ kMM_MAP5 = 0x05u << kMM_Shift, // EVEX.MAP5.
103
+ kMM_MAP6 = 0x06u << kMM_Shift, // EVEX.MAP6.
104
+
105
+ // `XOP` field is only used to force XOP prefix instead of VEX3 prefix. We know XOP encodings always use 0b1000
106
+ // bit of MM field and that no VEX and EVEX instruction use such bit yet, so we can use this bit to force XOP
107
+ // prefix to be emitted instead of VEX3 prefix. See `x86VEXPrefix` defined in `x86assembler.cpp`.
108
+ kMM_XOP08 = 0x08u << kMM_Shift, // XOP.M8.
109
+ kMM_XOP09 = 0x09u << kMM_Shift, // XOP.M9.
110
+ kMM_XOP0A = 0x0Au << kMM_Shift, // XOP.MA.
111
+
112
+ kMM_IsXOP_Shift= kMM_Shift + 3,
113
+ kMM_IsXOP = kMM_XOP08,
114
+
115
+ // NOTE: Force VEX3 allows to force to emit VEX3 instead of VEX2 in some cases (similar to forcing REX prefix).
116
+ // Force EVEX will force emitting EVEX prefix instead of VEX2|VEX3. EVEX-only instructions will have ForceEvex
117
+ // always set, however. instructions that can be encoded by either VEX or EVEX prefix should not have ForceEvex
118
+ // set.
119
+ kMM_ForceEvex = 0x10u << kMM_Shift, // Force 4-BYTE EVEX prefix.
120
+
121
+ // FPU_2B - Second-Byte of the Opcode used by FPU
122
+ // ----------------------------------------------
123
+ //
124
+ // Second byte opcode. This BYTE is ONLY used by FPU instructions and collides with 3 bits from `MM` and 5 bits
125
+ // from 'CDSHL' and 'CDTT'. It's fine as FPU and AVX512 flags are never used at the same time.
126
+ kFPU_2B_Shift = 10,
127
+ kFPU_2B_Mask = 0xFF << kFPU_2B_Shift,
128
+
129
+ // CDSHL & CDTT
130
+ // ------------
131
+ //
132
+ // Compressed displacement bits.
133
+ //
134
+ // Each opcode defines the base size (N) shift:
135
+ // [0]: BYTE (1 byte).
136
+ // [1]: WORD (2 bytes).
137
+ // [2]: DWORD (4 bytes - float/int32).
138
+ // [3]: QWORD (8 bytes - double/int64).
139
+ // [4]: OWORD (16 bytes - used by FV|FVM|M128).
140
+ //
141
+ // Which is then scaled by the instruction's TT (TupleType) into possible:
142
+ // [5]: YWORD (32 bytes)
143
+ // [6]: ZWORD (64 bytes)
144
+ //
145
+ // These bits are then adjusted before calling EmitModSib or EmitModVSib.
146
+ kCDSHL_Shift = 13,
147
+ kCDSHL_Mask = 0x7u << kCDSHL_Shift,
148
+
149
+ kCDSHL__ = 0x0u << kCDSHL_Shift, // Base element size not used.
150
+ kCDSHL_0 = 0x0u << kCDSHL_Shift, // N << 0.
151
+ kCDSHL_1 = 0x1u << kCDSHL_Shift, // N << 1.
152
+ kCDSHL_2 = 0x2u << kCDSHL_Shift, // N << 2.
153
+ kCDSHL_3 = 0x3u << kCDSHL_Shift, // N << 3.
154
+ kCDSHL_4 = 0x4u << kCDSHL_Shift, // N << 4.
155
+ kCDSHL_5 = 0x5u << kCDSHL_Shift, // N << 5.
156
+
157
+ // Compressed displacement tuple-type (specific to AsmJit).
158
+ //
159
+ // Since we store the base offset independently of CDTT we can simplify the number of 'TUPLE_TYPE' groups
160
+ // significantly and just handle special cases.
161
+ kCDTT_Shift = 16,
162
+ kCDTT_Mask = 0x3u << kCDTT_Shift,
163
+ kCDTT_None = 0x0u << kCDTT_Shift, // Does nothing.
164
+ kCDTT_ByLL = 0x1u << kCDTT_Shift, // Scales by LL (1x 2x 4x).
165
+ kCDTT_T1W = 0x2u << kCDTT_Shift, // Used to add 'W' to the shift.
166
+ kCDTT_DUP = 0x3u << kCDTT_Shift, // Special 'VMOVDDUP' case.
167
+
168
+ // Aliases that match names used in instruction manuals.
169
+ kCDTT__ = kCDTT_None,
170
+ kCDTT_FV = kCDTT_ByLL,
171
+ kCDTT_HV = kCDTT_ByLL,
172
+ kCDTT_QV = kCDTT_ByLL,
173
+ kCDTT_FVM = kCDTT_ByLL,
174
+ kCDTT_T1S = kCDTT_None,
175
+ kCDTT_T1F = kCDTT_None,
176
+ kCDTT_T1_4X = kCDTT_None,
177
+ kCDTT_T4X = kCDTT_None, // Alias to have only 3 letters.
178
+ kCDTT_T2 = kCDTT_None,
179
+ kCDTT_T4 = kCDTT_None,
180
+ kCDTT_T8 = kCDTT_None,
181
+ kCDTT_HVM = kCDTT_ByLL,
182
+ kCDTT_QVM = kCDTT_ByLL,
183
+ kCDTT_OVM = kCDTT_ByLL,
184
+ kCDTT_128 = kCDTT_None,
185
+
186
+ // `O` Field in ModR/M (??:xxx:???)
187
+ // --------------------------------
188
+
189
+ kModO_Shift = 18,
190
+ kModO_Mask = 0x7u << kModO_Shift,
191
+
192
+ kModO__ = 0x0u,
193
+ kModO_0 = 0x0u << kModO_Shift,
194
+ kModO_1 = 0x1u << kModO_Shift,
195
+ kModO_2 = 0x2u << kModO_Shift,
196
+ kModO_3 = 0x3u << kModO_Shift,
197
+ kModO_4 = 0x4u << kModO_Shift,
198
+ kModO_5 = 0x5u << kModO_Shift,
199
+ kModO_6 = 0x6u << kModO_Shift,
200
+ kModO_7 = 0x7u << kModO_Shift,
201
+
202
+ // `RM` Field in ModR/M (??:???:xxx)
203
+ // ---------------------------------
204
+ //
205
+ // Second data field used by ModR/M byte. This is only used by few instructions that use OPCODE+MOD/RM where both
206
+ // values in Mod/RM are part of the opcode.
207
+
208
+ kModRM_Shift = 13,
209
+ kModRM_Mask = 0x7u << kModRM_Shift,
210
+
211
+ kModRM__ = 0x0u,
212
+ kModRM_0 = 0x0u << kModRM_Shift,
213
+ kModRM_1 = 0x1u << kModRM_Shift,
214
+ kModRM_2 = 0x2u << kModRM_Shift,
215
+ kModRM_3 = 0x3u << kModRM_Shift,
216
+ kModRM_4 = 0x4u << kModRM_Shift,
217
+ kModRM_5 = 0x5u << kModRM_Shift,
218
+ kModRM_6 = 0x6u << kModRM_Shift,
219
+ kModRM_7 = 0x7u << kModRM_Shift,
220
+
221
+ // `PP` Field
222
+ // ----------
223
+ //
224
+ // These fields are stored deliberately right after each other as it makes it easier to construct VEX prefix from
225
+ // the opcode value stored in the instruction database.
226
+ //
227
+ // Two meanings:
228
+ // * "PP" field in AVX/XOP/AVX-512 instruction.
229
+ // * Mandatory Prefix in legacy encoding.
230
+ //
231
+ // AVX reserves 2 bits for `PP` field, but AsmJit extends the storage by 1 more bit that is used to emit 9B prefix
232
+ // for some X87-FPU instructions.
233
+
234
+ kPP_Shift = 21,
235
+ kPP_VEXMask = 0x03u << kPP_Shift, // PP field mask used by VEX/EVEX.
236
+ kPP_FPUMask = 0x07u << kPP_Shift, // Mask used by EMIT_PP, also includes '0x9B'.
237
+ kPP_00 = 0x00u << kPP_Shift,
238
+ kPP_66 = 0x01u << kPP_Shift,
239
+ kPP_F3 = 0x02u << kPP_Shift,
240
+ kPP_F2 = 0x03u << kPP_Shift,
241
+
242
+ kPP_9B = 0x07u << kPP_Shift, // AsmJit specific to emit FPU's '9B' byte.
243
+
244
+ // REX|VEX|EVEX B|X|R|W Bits
245
+ // -------------------------
246
+ //
247
+ // NOTE: REX.[B|X|R] are never stored within the opcode itself, they are reserved by AsmJit are are added
248
+ // dynamically to the opcode to represent [REX|VEX|EVEX].[B|X|R] bits. REX.W can be stored in DB as it's sometimes
249
+ // part of the opcode itself.
250
+
251
+ // These must be binary compatible with instruction options.
252
+ kREX_Shift = 24,
253
+ kREX_Mask = 0x0Fu << kREX_Shift,
254
+ kB = 0x01u << kREX_Shift, // Never stored in DB, used by encoder.
255
+ kX = 0x02u << kREX_Shift, // Never stored in DB, used by encoder.
256
+ kR = 0x04u << kREX_Shift, // Never stored in DB, used by encoder.
257
+ kW = 0x08u << kREX_Shift,
258
+ kW_Shift = kREX_Shift + 3,
259
+
260
+ kW__ = 0u << kW_Shift, // REX.W/VEX.W is unspecified.
261
+ kW_x = 0u << kW_Shift, // REX.W/VEX.W is based on instruction operands.
262
+ kW_I = 0u << kW_Shift, // REX.W/VEX.W is ignored (WIG).
263
+ kW_0 = 0u << kW_Shift, // REX.W/VEX.W is 0 (W0).
264
+ kW_1 = 1u << kW_Shift, // REX.W/VEX.W is 1 (W1).
265
+
266
+ // EVEX.W Field
267
+ // ------------
268
+ //
269
+ // `W` field used by EVEX instruction encoding.
270
+
271
+ kEvex_W_Shift = 28,
272
+ kEvex_W_Mask = 1u << kEvex_W_Shift,
273
+
274
+ kEvex_W__ = 0u << kEvex_W_Shift, // EVEX.W is unspecified (not EVEX instruction).
275
+ kEvex_W_x = 0u << kEvex_W_Shift, // EVEX.W is based on instruction operands.
276
+ kEvex_W_I = 0u << kEvex_W_Shift, // EVEX.W is ignored (WIG).
277
+ kEvex_W_0 = 0u << kEvex_W_Shift, // EVEX.W is 0 (W0).
278
+ kEvex_W_1 = 1u << kEvex_W_Shift, // EVEX.W is 1 (W1).
279
+
280
+ // `L` or `LL` field in AVX/XOP/AVX-512
281
+ // ------------------------------------
282
+ //
283
+ // VEX/XOP prefix can only use the first bit `L.128` or `L.256`. EVEX prefix prefix makes it possible to use also
284
+ // `L.512`. If the instruction set manual describes an instruction by `LIG` it means that the `L` field is ignored
285
+ // and AsmJit defaults to `0` in such case.
286
+ kLL_Shift = 29,
287
+ kLL_Mask = 0x3u << kLL_Shift,
288
+
289
+ kLL__ = 0x0u << kLL_Shift, // LL is unspecified.
290
+ kLL_x = 0x0u << kLL_Shift, // LL is based on instruction operands.
291
+ kLL_I = 0x0u << kLL_Shift, // LL is ignored (LIG).
292
+ kLL_0 = 0x0u << kLL_Shift, // LL is 0 (L.128).
293
+ kLL_1 = 0x1u << kLL_Shift, // LL is 1 (L.256).
294
+ kLL_2 = 0x2u << kLL_Shift, // LL is 2 (L.512).
295
+
296
+ // Opcode Combinations
297
+ // -------------------
298
+
299
+ k0 = 0, // '__' (no prefix, used internally).
300
+ k000000 = kPP_00 | kMM_00, // '__' (no prefix, to be the same width as others).
301
+ k000F00 = kPP_00 | kMM_0F, // '0F'
302
+ k000F01 = kPP_00 | kMM_0F01, // '0F01'
303
+ k000F0F = kPP_00 | kMM_0F, // '0F0F' - 3DNOW, equal to 0x0F, must have special encoding to take effect.
304
+ k000F38 = kPP_00 | kMM_0F38, // 'NP.0F38'
305
+ k000F3A = kPP_00 | kMM_0F3A, // 'NP.0F3A'
306
+ k00MAP5 = kPP_00 | kMM_MAP5, // 'NP.MAP5'
307
+ k00MAP6 = kPP_00 | kMM_MAP6, // 'NP.MAP5'
308
+ k660000 = kPP_66 | kMM_00, // '66'
309
+ k660F00 = kPP_66 | kMM_0F, // '66.0F'
310
+ k660F01 = kPP_66 | kMM_0F01, // '66.0F01'
311
+ k660F38 = kPP_66 | kMM_0F38, // '66.0F38'
312
+ k660F3A = kPP_66 | kMM_0F3A, // '66.0F3A'
313
+ k66MAP5 = kPP_66 | kMM_MAP5, // '66.MAP5'
314
+ k66MAP6 = kPP_66 | kMM_MAP6, // '66.MAP5'
315
+ kF20000 = kPP_F2 | kMM_00, // 'F2'
316
+ kF20F00 = kPP_F2 | kMM_0F, // 'F2.0F'
317
+ kF20F01 = kPP_F2 | kMM_0F01, // 'F2.0F01'
318
+ kF20F38 = kPP_F2 | kMM_0F38, // 'F2.0F38'
319
+ kF20F3A = kPP_F2 | kMM_0F3A, // 'F2.0F3A'
320
+ kF2MAP5 = kPP_F2 | kMM_MAP5, // 'F2.MAP5'
321
+ kF2MAP6 = kPP_F2 | kMM_MAP6, // 'F2.MAP5'
322
+ kF30000 = kPP_F3 | kMM_00, // 'F3'
323
+ kF30F00 = kPP_F3 | kMM_0F, // 'F3.0F'
324
+ kF30F01 = kPP_F3 | kMM_0F01, // 'F3.0F01'
325
+ kF30F38 = kPP_F3 | kMM_0F38, // 'F3.0F38'
326
+ kF30F3A = kPP_F3 | kMM_0F3A, // 'F3.0F3A'
327
+ kF3MAP5 = kPP_F3 | kMM_MAP5, // 'F3.MAP5'
328
+ kF3MAP6 = kPP_F3 | kMM_MAP6, // 'F3.MAP5'
329
+ kFPU_00 = kPP_00 | kMM_00, // '__' (FPU)
330
+ kFPU_9B = kPP_9B | kMM_00, // '9B' (FPU)
331
+ kXOP_M8 = kPP_00 | kMM_XOP08, // 'M8' (XOP)
332
+ kXOP_M9 = kPP_00 | kMM_XOP09, // 'M9' (XOP)
333
+ kXOP_MA = kPP_00 | kMM_XOP0A // 'MA' (XOP)
334
+ };
335
+
336
+ // Opcode Builder
337
+ // --------------
338
+
339
+ inline uint32_t get() const noexcept { return v; }
340
+
341
+ inline bool hasW() const noexcept { return (v & kW) != 0; }
342
+ inline bool has66h() const noexcept { return (v & kPP_66) != 0; }
343
+
344
+ inline Opcode& add(uint32_t x) noexcept { return operator+=(x); }
345
+
346
+ inline Opcode& add66h() noexcept { return operator|=(kPP_66); }
347
+ template<typename T>
348
+ inline Opcode& add66hIf(T exp) noexcept { return operator|=(uint32_t(exp) << kPP_Shift); }
349
+ template<typename T>
350
+ inline Opcode& add66hBySize(T size) noexcept { return add66hIf(size == 2); }
351
+
352
+ inline Opcode& addW() noexcept { return operator|=(kW); }
353
+ template<typename T>
354
+ inline Opcode& addWIf(T exp) noexcept { return operator|=(uint32_t(exp) << kW_Shift); }
355
+ template<typename T>
356
+ inline Opcode& addWBySize(T size) noexcept { return addWIf(size == 8); }
357
+
358
+ template<typename T>
359
+ inline Opcode& addPrefixBySize(T size) noexcept {
360
+ static const uint32_t mask[16] = {
361
+ 0, // #0
362
+ 0, // #1 -> nothing (already handled or not possible)
363
+ kPP_66, // #2 -> 66H
364
+ 0, // #3
365
+ 0, // #4 -> nothing
366
+ 0, // #5
367
+ 0, // #6
368
+ 0, // #7
369
+ kW // #8 -> REX.W
370
+ };
371
+ return operator|=(mask[size & 0xF]);
372
+ }
373
+
374
+ template<typename T>
375
+ inline Opcode& addArithBySize(T size) noexcept {
376
+ static const uint32_t mask[16] = {
377
+ 0, // #0
378
+ 0, // #1 -> nothing
379
+ 1 | kPP_66, // #2 -> NOT_BYTE_OP(1) and 66H
380
+ 0, // #3
381
+ 1, // #4 -> NOT_BYTE_OP(1)
382
+ 0, // #5
383
+ 0, // #6
384
+ 0, // #7
385
+ 1 | kW // #8 -> NOT_BYTE_OP(1) and REX.W
386
+ };
387
+ return operator|=(mask[size & 0xF]);
388
+ }
389
+
390
+ inline Opcode& forceEvex() noexcept { return operator|=(kMM_ForceEvex); }
391
+ template<typename T>
392
+ inline Opcode& forceEvexIf(T exp) noexcept { return operator|=(uint32_t(exp) << Support::ConstCTZ<uint32_t(kMM_ForceEvex)>::value); }
393
+
394
+ //! Extract `O` field (R) from the opcode (specified as /0..7 in instruction manuals).
395
+ inline uint32_t extractModO() const noexcept {
396
+ return (v >> kModO_Shift) & 0x07;
397
+ }
398
+
399
+ //! Extract `RM` field (RM) from the opcode (usually specified as another opcode value).
400
+ inline uint32_t extractModRM() const noexcept {
401
+ return (v >> kModRM_Shift) & 0x07;
402
+ }
403
+
404
+ //! Extract `REX` prefix from opcode combined with `options`.
405
+ inline uint32_t extractRex(InstOptions options) const noexcept {
406
+ // kREX was designed in a way that when shifted there will be no bytes set except REX.[B|X|R|W].
407
+ // The returned value forms a real REX prefix byte. This case should be unit-tested as well.
408
+ return (v | uint32_t(options)) >> kREX_Shift;
409
+ }
410
+
411
+ inline uint32_t extractLLMMMMM(InstOptions options) const noexcept {
412
+ uint32_t llMmmmm = uint32_t(v & (kLL_Mask | kMM_Mask));
413
+ uint32_t vexEvex = uint32_t(options & InstOptions::kX86_Evex);
414
+ return (llMmmmm | vexEvex) >> kMM_Shift;
415
+ }
416
+
417
+ inline Opcode& operator=(uint32_t x) noexcept { v = x; return *this; }
418
+ inline Opcode& operator+=(uint32_t x) noexcept { v += x; return *this; }
419
+ inline Opcode& operator-=(uint32_t x) noexcept { v -= x; return *this; }
420
+ inline Opcode& operator&=(uint32_t x) noexcept { v &= x; return *this; }
421
+ inline Opcode& operator|=(uint32_t x) noexcept { v |= x; return *this; }
422
+ inline Opcode& operator^=(uint32_t x) noexcept { v ^= x; return *this; }
423
+
424
+ inline uint32_t operator&(uint32_t x) const noexcept { return v & x; }
425
+ inline uint32_t operator|(uint32_t x) const noexcept { return v | x; }
426
+ inline uint32_t operator^(uint32_t x) const noexcept { return v ^ x; }
427
+ inline uint32_t operator<<(uint32_t x) const noexcept { return v << x; }
428
+ inline uint32_t operator>>(uint32_t x) const noexcept { return v >> x; }
429
+ };
430
+
431
+ //! \}
432
+ //! \endcond
433
+
434
+ ASMJIT_END_SUB_NAMESPACE
435
+
436
+ #endif // ASMJIT_X86_X86OPCODE_P_H_INCLUDED
@@ -0,0 +1,231 @@
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
+ #include "../core/api-build_p.h"
7
+ #if !defined(ASMJIT_NO_X86)
8
+
9
+ #include "../core/misc_p.h"
10
+ #include "../x86/x86operand.h"
11
+
12
+ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
13
+
14
+ // x86::Operand - Tests
15
+ // ====================
16
+
17
+ #if defined(ASMJIT_TEST)
18
+ UNIT(x86_operand) {
19
+ Label L(1000); // Label with some ID.
20
+
21
+ INFO("Checking basic properties of built-in X86 registers");
22
+ EXPECT(gpb(Gp::kIdAx) == al);
23
+ EXPECT(gpb(Gp::kIdBx) == bl);
24
+ EXPECT(gpb(Gp::kIdCx) == cl);
25
+ EXPECT(gpb(Gp::kIdDx) == dl);
26
+
27
+ EXPECT(gpb_lo(Gp::kIdAx) == al);
28
+ EXPECT(gpb_lo(Gp::kIdBx) == bl);
29
+ EXPECT(gpb_lo(Gp::kIdCx) == cl);
30
+ EXPECT(gpb_lo(Gp::kIdDx) == dl);
31
+
32
+ EXPECT(gpb_hi(Gp::kIdAx) == ah);
33
+ EXPECT(gpb_hi(Gp::kIdBx) == bh);
34
+ EXPECT(gpb_hi(Gp::kIdCx) == ch);
35
+ EXPECT(gpb_hi(Gp::kIdDx) == dh);
36
+
37
+ EXPECT(gpw(Gp::kIdAx) == ax);
38
+ EXPECT(gpw(Gp::kIdBx) == bx);
39
+ EXPECT(gpw(Gp::kIdCx) == cx);
40
+ EXPECT(gpw(Gp::kIdDx) == dx);
41
+
42
+ EXPECT(gpd(Gp::kIdAx) == eax);
43
+ EXPECT(gpd(Gp::kIdBx) == ebx);
44
+ EXPECT(gpd(Gp::kIdCx) == ecx);
45
+ EXPECT(gpd(Gp::kIdDx) == edx);
46
+
47
+ EXPECT(gpq(Gp::kIdAx) == rax);
48
+ EXPECT(gpq(Gp::kIdBx) == rbx);
49
+ EXPECT(gpq(Gp::kIdCx) == rcx);
50
+ EXPECT(gpq(Gp::kIdDx) == rdx);
51
+
52
+ EXPECT(gpb(Gp::kIdAx) != dl);
53
+ EXPECT(gpw(Gp::kIdBx) != cx);
54
+ EXPECT(gpd(Gp::kIdCx) != ebx);
55
+ EXPECT(gpq(Gp::kIdDx) != rax);
56
+
57
+ INFO("Checking if x86::reg(...) matches built-in IDs");
58
+ EXPECT(gpb(5) == bpl);
59
+ EXPECT(gpw(5) == bp);
60
+ EXPECT(gpd(5) == ebp);
61
+ EXPECT(gpq(5) == rbp);
62
+ EXPECT(st(5) == st5);
63
+ EXPECT(mm(5) == mm5);
64
+ EXPECT(k(5) == k5);
65
+ EXPECT(cr(5) == cr5);
66
+ EXPECT(dr(5) == dr5);
67
+ EXPECT(xmm(5) == xmm5);
68
+ EXPECT(ymm(5) == ymm5);
69
+ EXPECT(zmm(5) == zmm5);
70
+
71
+ INFO("Checking x86::Gp register properties");
72
+ EXPECT(Gp().isReg() == true);
73
+ EXPECT(eax.isReg() == true);
74
+ EXPECT(eax.id() == 0);
75
+ EXPECT(eax.size() == 4);
76
+ EXPECT(eax.type() == RegType::kX86_Gpd);
77
+ EXPECT(eax.group() == RegGroup::kGp);
78
+
79
+ INFO("Checking x86::Xmm register properties");
80
+ EXPECT(Xmm().isReg() == true);
81
+ EXPECT(xmm4.isReg() == true);
82
+ EXPECT(xmm4.id() == 4);
83
+ EXPECT(xmm4.size() == 16);
84
+ EXPECT(xmm4.type() == RegType::kX86_Xmm);
85
+ EXPECT(xmm4.group() == RegGroup::kVec);
86
+ EXPECT(xmm4.isVec());
87
+
88
+ INFO("Checking x86::Ymm register properties");
89
+ EXPECT(Ymm().isReg() == true);
90
+ EXPECT(ymm5.isReg() == true);
91
+ EXPECT(ymm5.id() == 5);
92
+ EXPECT(ymm5.size() == 32);
93
+ EXPECT(ymm5.type() == RegType::kX86_Ymm);
94
+ EXPECT(ymm5.group() == RegGroup::kVec);
95
+ EXPECT(ymm5.isVec());
96
+
97
+ INFO("Checking x86::Zmm register properties");
98
+ EXPECT(Zmm().isReg() == true);
99
+ EXPECT(zmm6.isReg() == true);
100
+ EXPECT(zmm6.id() == 6);
101
+ EXPECT(zmm6.size() == 64);
102
+ EXPECT(zmm6.type() == RegType::kX86_Zmm);
103
+ EXPECT(zmm6.group() == RegGroup::kVec);
104
+ EXPECT(zmm6.isVec());
105
+
106
+ INFO("Checking x86::Vec register properties");
107
+ EXPECT(Vec().isReg() == true);
108
+ // Converts a VEC register to a type of the passed register, but keeps the ID.
109
+ EXPECT(xmm4.cloneAs(ymm10) == ymm4);
110
+ EXPECT(xmm4.cloneAs(zmm11) == zmm4);
111
+ EXPECT(ymm5.cloneAs(xmm12) == xmm5);
112
+ EXPECT(ymm5.cloneAs(zmm13) == zmm5);
113
+ EXPECT(zmm6.cloneAs(xmm14) == xmm6);
114
+ EXPECT(zmm6.cloneAs(ymm15) == ymm6);
115
+
116
+ EXPECT(xmm7.xmm() == xmm7);
117
+ EXPECT(xmm7.ymm() == ymm7);
118
+ EXPECT(xmm7.zmm() == zmm7);
119
+
120
+ EXPECT(ymm7.xmm() == xmm7);
121
+ EXPECT(ymm7.ymm() == ymm7);
122
+ EXPECT(ymm7.zmm() == zmm7);
123
+
124
+ EXPECT(zmm7.xmm() == xmm7);
125
+ EXPECT(zmm7.ymm() == ymm7);
126
+ EXPECT(zmm7.zmm() == zmm7);
127
+
128
+ INFO("Checking x86::Mm register properties");
129
+ EXPECT(Mm().isReg() == true);
130
+ EXPECT(mm2.isReg() == true);
131
+ EXPECT(mm2.id() == 2);
132
+ EXPECT(mm2.size() == 8);
133
+ EXPECT(mm2.type() == RegType::kX86_Mm);
134
+ EXPECT(mm2.group() == RegGroup::kX86_MM);
135
+
136
+ INFO("Checking x86::KReg register properties");
137
+ EXPECT(KReg().isReg() == true);
138
+ EXPECT(k3.isReg() == true);
139
+ EXPECT(k3.id() == 3);
140
+ EXPECT(k3.size() == 0);
141
+ EXPECT(k3.type() == RegType::kX86_KReg);
142
+ EXPECT(k3.group() == RegGroup::kX86_K);
143
+
144
+ INFO("Checking x86::St register properties");
145
+ EXPECT(St().isReg() == true);
146
+ EXPECT(st1.isReg() == true);
147
+ EXPECT(st1.id() == 1);
148
+ EXPECT(st1.size() == 10);
149
+ EXPECT(st1.type() == RegType::kX86_St);
150
+ EXPECT(st1.group() == RegGroup::kX86_St);
151
+
152
+ INFO("Checking if default constructed regs behave as expected");
153
+ EXPECT(Reg().isValid() == false);
154
+ EXPECT(Gp().isValid() == false);
155
+ EXPECT(Xmm().isValid() == false);
156
+ EXPECT(Ymm().isValid() == false);
157
+ EXPECT(Zmm().isValid() == false);
158
+ EXPECT(Mm().isValid() == false);
159
+ EXPECT(KReg().isValid() == false);
160
+ EXPECT(SReg().isValid() == false);
161
+ EXPECT(CReg().isValid() == false);
162
+ EXPECT(DReg().isValid() == false);
163
+ EXPECT(St().isValid() == false);
164
+ EXPECT(Bnd().isValid() == false);
165
+
166
+ INFO("Checking x86::Mem operand");
167
+ Mem m;
168
+ EXPECT(m == Mem(), "Two default constructed x86::Mem operands must be equal");
169
+
170
+ m = ptr(L);
171
+ EXPECT(m.hasBase() == true);
172
+ EXPECT(m.hasBaseReg() == false);
173
+ EXPECT(m.hasBaseLabel() == true);
174
+ EXPECT(m.hasOffset() == false);
175
+ EXPECT(m.isOffset64Bit() == false);
176
+ EXPECT(m.offset() == 0);
177
+ EXPECT(m.offsetLo32() == 0);
178
+
179
+ m = ptr(0x0123456789ABCDEFu);
180
+ EXPECT(m.hasBase() == false);
181
+ EXPECT(m.hasBaseReg() == false);
182
+ EXPECT(m.hasIndex() == false);
183
+ EXPECT(m.hasIndexReg() == false);
184
+ EXPECT(m.hasOffset() == true);
185
+ EXPECT(m.isOffset64Bit() == true);
186
+ EXPECT(m.offset() == int64_t(0x0123456789ABCDEFu));
187
+ EXPECT(m.offsetLo32() == int32_t(0x89ABCDEFu));
188
+ m.addOffset(1);
189
+ EXPECT(m.offset() == int64_t(0x0123456789ABCDF0u));
190
+
191
+ m = ptr(0x0123456789ABCDEFu, rdi, 3);
192
+ EXPECT(m.hasSegment() == false);
193
+ EXPECT(m.hasBase() == false);
194
+ EXPECT(m.hasBaseReg() == false);
195
+ EXPECT(m.hasIndex() == true);
196
+ EXPECT(m.hasIndexReg() == true);
197
+ EXPECT(m.indexType() == rdi.type());
198
+ EXPECT(m.indexId() == rdi.id());
199
+ EXPECT(m.shift() == 3);
200
+ EXPECT(m.hasOffset() == true);
201
+ EXPECT(m.isOffset64Bit() == true);
202
+ EXPECT(m.offset() == int64_t(0x0123456789ABCDEFu));
203
+ EXPECT(m.offsetLo32() == int32_t(0x89ABCDEFu));
204
+ m.resetIndex();
205
+ EXPECT(m.hasIndex() == false);
206
+ EXPECT(m.hasIndexReg() == false);
207
+
208
+ m = ptr(rax);
209
+ EXPECT(m.hasBase() == true);
210
+ EXPECT(m.hasBaseReg() == true);
211
+ EXPECT(m.baseType() == rax.type());
212
+ EXPECT(m.baseId() == rax.id());
213
+ EXPECT(m.hasIndex() == false);
214
+ EXPECT(m.hasIndexReg() == false);
215
+ EXPECT(m.indexType() == RegType::kNone);
216
+ EXPECT(m.indexId() == 0);
217
+ EXPECT(m.hasOffset() == false);
218
+ EXPECT(m.isOffset64Bit() == false);
219
+ EXPECT(m.offset() == 0);
220
+ EXPECT(m.offsetLo32() == 0);
221
+ m.setIndex(rsi);
222
+ EXPECT(m.hasIndex() == true);
223
+ EXPECT(m.hasIndexReg() == true);
224
+ EXPECT(m.indexType() == rsi.type());
225
+ EXPECT(m.indexId() == rsi.id());
226
+ }
227
+ #endif
228
+
229
+ ASMJIT_END_SUB_NAMESPACE
230
+
231
+ #endif // !ASMJIT_NO_X86